diff options
author | Terje Bergstrom <tbergstrom@nvidia.com> | 2011-12-19 15:12:06 +0200 |
---|---|---|
committer | Varun Wadekar <vwadekar@nvidia.com> | 2011-12-22 11:32:23 +0530 |
commit | d993b01464a87a76d0b859e570cb78caaf1996f9 (patch) | |
tree | 92b3af033ec92c282f196848d745ec34a9e23d4f /drivers/video | |
parent | 204b15d959afb9d3d675c949262ce545c17e7c69 (diff) |
video: tegra: host: Move timeout to hwctx & job structs
Timeout struct contains fields which are accessed even after client has
quit. Move the fields to hwctx and nvhost_job so that they can be
accessed when submits complete.
Bug 917340
Change-Id: I322c38d32bc801aa9b061355a17be7f605692e18
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/71004
Reviewed-by: Automatic_Commit_Validation_User
Tested-by: Varun Wadekar <vwadekar@nvidia.com>
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/tegra/host/3dctx_common.c | 88 | ||||
-rw-r--r-- | drivers/video/tegra/host/chip_support.h | 1 | ||||
-rw-r--r-- | drivers/video/tegra/host/dev.c | 22 | ||||
-rw-r--r-- | drivers/video/tegra/host/dev.h | 7 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_cdma.c | 73 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_cdma.h | 6 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_hwctx.h | 4 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_job.c | 16 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_job.h | 11 | ||||
-rw-r--r-- | drivers/video/tegra/host/t20/cdma_t20.c | 14 | ||||
-rw-r--r-- | drivers/video/tegra/host/t20/channel_t20.c | 19 | ||||
-rw-r--r-- | drivers/video/tegra/host/t20/t20.c | 14 |
12 files changed, 86 insertions, 189 deletions
diff --git a/drivers/video/tegra/host/3dctx_common.c b/drivers/video/tegra/host/3dctx_common.c index a3f38d9127cb..e7673c54e31a 100644 --- a/drivers/video/tegra/host/3dctx_common.c +++ b/drivers/video/tegra/host/3dctx_common.c @@ -25,6 +25,7 @@ #include <mach/nvmap.h> #include <linux/slab.h> #include "3dctx_common.h" +#include "t20/t20.h" #include "t20/hardware_t20.h" #include "t20/syncpt_t20.h" #include "nvhost_hwctx.h" @@ -148,90 +149,5 @@ void nvhost_3dctx_put(struct nvhost_hwctx *ctx) int nvhost_3dctx_prepare_power_off(struct nvhost_module *mod) { - struct nvhost_channel *ch = - container_of(mod, struct nvhost_channel, mod); - struct nvhost_hwctx *hwctx_to_save; - struct nvhost_job *job; - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); - u32 syncpt_incrs, syncpt_val; - int err = 0; - void *ref; - void *ctx_waiter = NULL, *wakeup_waiter = NULL; - - ctx_waiter = nvhost_intr_alloc_waiter(); - wakeup_waiter = nvhost_intr_alloc_waiter(); - if (!ctx_waiter || !wakeup_waiter) { - err = -ENOMEM; - goto done; - } - if (mod->desc->busy) - mod->desc->busy(mod); - - mutex_lock(&ch->submitlock); - hwctx_to_save = ch->cur_ctx; - if (!hwctx_to_save) { - mutex_unlock(&ch->submitlock); - goto done; - } - - job = nvhost_job_alloc(ch, hwctx_to_save, - NULL, - ch->dev->nvmap, 0, hwctx_to_save->timeout); - if (IS_ERR_OR_NULL(job)) { - err = PTR_ERR(job); - mutex_unlock(&ch->submitlock); - goto done; - } - - err = nvhost_cdma_begin(&ch->cdma, hwctx_to_save->timeout); - if (err) { - mutex_unlock(&ch->submitlock); - goto done; - } - - hwctx_to_save->valid = true; - ch->ctxhandler.get(hwctx_to_save); - ch->cur_ctx = NULL; - - syncpt_incrs = hwctx_to_save->save_incrs; - syncpt_val = nvhost_syncpt_incr_max(&ch->dev->syncpt, - NVSYNCPT_3D, syncpt_incrs); - - job->syncpt_id = NVSYNCPT_3D; - job->syncpt_incrs = syncpt_incrs; - job->syncpt_end = syncpt_val; - - ch->ctxhandler.save_push(&ch->cdma, hwctx_to_save); - nvhost_cdma_end(&ch->cdma, job); - nvhost_job_put(job); - job = NULL; - - err = nvhost_intr_add_action(&ch->dev->intr, NVSYNCPT_3D, - syncpt_val - syncpt_incrs + hwctx_to_save->save_thresh, - NVHOST_INTR_ACTION_CTXSAVE, hwctx_to_save, - ctx_waiter, - NULL); - ctx_waiter = NULL; - WARN(err, "Failed to set context save interrupt"); - - err = nvhost_intr_add_action(&ch->dev->intr, NVSYNCPT_3D, syncpt_val, - NVHOST_INTR_ACTION_WAKEUP, &wq, - wakeup_waiter, - &ref); - wakeup_waiter = NULL; - WARN(err, "Failed to set wakeup interrupt"); - wait_event(wq, - nvhost_syncpt_min_cmp(&ch->dev->syncpt, - NVSYNCPT_3D, syncpt_val)); - - nvhost_intr_put_ref(&ch->dev->intr, ref); - - nvhost_cdma_update(&ch->cdma); - - mutex_unlock(&ch->submitlock); - -done: - kfree(ctx_waiter); - kfree(wakeup_waiter); - return err; + return nvhost_t20_save_context(mod, NVSYNCPT_3D); } diff --git a/drivers/video/tegra/host/chip_support.h b/drivers/video/tegra/host/chip_support.h index d909d34bbe73..3b8c4dc46b45 100644 --- a/drivers/video/tegra/host/chip_support.h +++ b/drivers/video/tegra/host/chip_support.h @@ -49,7 +49,6 @@ struct nvhost_chip_support { int (*submit)(struct nvhost_job *job); int (*read3dreg)(struct nvhost_channel *channel, struct nvhost_hwctx *hwctx, - struct nvhost_userctx_timeout *timeout, u32 offset, u32 *value); } channel; diff --git a/drivers/video/tegra/host/dev.c b/drivers/video/tegra/host/dev.c index 47d6daa4a482..fe5fb22add92 100644 --- a/drivers/video/tegra/host/dev.c +++ b/drivers/video/tegra/host/dev.c @@ -61,8 +61,9 @@ struct nvhost_channel_userctx { int num_relocshifts; struct nvhost_job *job; struct nvmap_client *nvmap; - struct nvhost_userctx_timeout timeout; + u32 timeout; u32 priority; + int clientid; }; struct nvhost_ctrl_userctx { @@ -155,13 +156,12 @@ static int nvhost_channelopen(struct inode *inode, struct file *filp) priv->hwctx = ch->ctxhandler.alloc(ch); if (!priv->hwctx) goto fail; - priv->hwctx->timeout = &priv->timeout; - priv->timeout.hwctx = priv->hwctx; } priv->priority = NVHOST_PRIORITY_MEDIUM; + priv->clientid = atomic_add_return(1, &ch->dev->clientid); priv->job = nvhost_job_alloc(ch, priv->hwctx, &priv->hdr, - NULL, priv->priority, &priv->timeout); + NULL, priv->priority, priv->clientid); if (!priv->job) goto fail; @@ -187,9 +187,11 @@ static int set_submit(struct nvhost_channel_userctx *ctx) ctx->job = nvhost_job_realloc(ctx->job, &ctx->hdr, ctx->nvmap, - ctx->priority); + ctx->priority, + ctx->clientid); if (!ctx->job) return -ENOMEM; + ctx->job->timeout = ctx->timeout; if (ctx->hdr.submit_version >= NVHOST_SUBMIT_VERSION_V2) ctx->num_relocshifts = ctx->hdr.num_relocs; @@ -340,9 +342,8 @@ static int nvhost_ioctl_channel_flush( if ((nvhost_debug_force_timeout_pid == current->tgid) && (nvhost_debug_force_timeout_channel == ctx->ch->chid)) { - ctx->timeout.timeout = nvhost_debug_force_timeout_val; + ctx->timeout = nvhost_debug_force_timeout_val; } - ctx->timeout.syncpt_id = ctx->hdr.syncpt_id; trace_write_cmdbufs(ctx->job); @@ -361,7 +362,6 @@ static int nvhost_ioctl_channel_read_3d_reg( { BUG_ON(!channel_op(ctx->ch).read3dreg); return channel_op(ctx->ch).read3dreg(ctx->ch, ctx->hwctx, - &ctx->timeout, args->offset, &args->value); } @@ -480,15 +480,15 @@ static long nvhost_channelctl(struct file *filp, break; } case NVHOST_IOCTL_CHANNEL_SET_TIMEOUT: - priv->timeout.timeout = + priv->timeout = (u32)((struct nvhost_set_timeout_args *)buf)->timeout; dev_dbg(&priv->ch->dev->pdev->dev, "%s: setting buffer timeout (%d ms) for userctx 0x%p\n", - __func__, priv->timeout.timeout, priv); + __func__, priv->timeout, priv); break; case NVHOST_IOCTL_CHANNEL_GET_TIMEDOUT: ((struct nvhost_get_param_args *)buf)->value = - priv->timeout.has_timedout; + priv->hwctx->has_timedout; break; case NVHOST_IOCTL_CHANNEL_SET_PRIORITY: priv->priority = diff --git a/drivers/video/tegra/host/dev.h b/drivers/video/tegra/host/dev.h index 45217a3ea1a1..3d05da8c53e8 100644 --- a/drivers/video/tegra/host/dev.h +++ b/drivers/video/tegra/host/dev.h @@ -54,13 +54,8 @@ struct nvhost_master { u32 sync_queue_size; struct nvhost_chip_support op; -}; -struct nvhost_userctx_timeout { - u32 timeout; - bool has_timedout; - struct nvhost_hwctx *hwctx; - int syncpt_id; + atomic_t clientid; }; void nvhost_debug_init(struct nvhost_master *master); diff --git a/drivers/video/tegra/host/nvhost_cdma.c b/drivers/video/tegra/host/nvhost_cdma.c index efa6a1104ac9..63ce365e990e 100644 --- a/drivers/video/tegra/host/nvhost_cdma.c +++ b/drivers/video/tegra/host/nvhost_cdma.c @@ -137,23 +137,23 @@ unsigned int nvhost_cdma_wait_locked(struct nvhost_cdma *cdma, * Start timer for a buffer submition that has completed yet. * Must be called with the cdma lock held. */ -static void cdma_start_timer_locked(struct nvhost_cdma *cdma, u32 syncpt_id, - u32 syncpt_val, - struct nvhost_userctx_timeout *timeout) +static void cdma_start_timer_locked(struct nvhost_cdma *cdma, + struct nvhost_job *job) { - BUG_ON(!timeout); - if (cdma->timeout.ctx_timeout) { + BUG_ON(!job); + if (cdma->timeout.clientid) { /* timer already started */ return; } - cdma->timeout.ctx_timeout = timeout; - cdma->timeout.syncpt_id = syncpt_id; - cdma->timeout.syncpt_val = syncpt_val; + cdma->timeout.ctx = job->hwctx; + cdma->timeout.clientid = job->clientid; + cdma->timeout.syncpt_id = job->syncpt_id; + cdma->timeout.syncpt_val = job->syncpt_end; cdma->timeout.start_ktime = ktime_get(); schedule_delayed_work(&cdma->timeout.wq, - msecs_to_jiffies(timeout->timeout)); + msecs_to_jiffies(job->timeout)); } /** @@ -163,7 +163,8 @@ static void cdma_start_timer_locked(struct nvhost_cdma *cdma, u32 syncpt_id, static void stop_cdma_timer_locked(struct nvhost_cdma *cdma) { cancel_delayed_work(&cdma->timeout.wq); - cdma->timeout.ctx_timeout = NULL; + cdma->timeout.ctx = NULL; + cdma->timeout.clientid = 0; } /** @@ -205,15 +206,13 @@ static void update_cdma_locked(struct nvhost_cdma *cdma) if (!nvhost_syncpt_min_cmp(sp, job->syncpt_id, job->syncpt_end)) { /* Start timer on next pending syncpt */ - if (job->timeout->timeout) { - cdma_start_timer_locked(cdma, job->syncpt_id, - job->syncpt_end, job->timeout); - } + if (job->timeout) + cdma_start_timer_locked(cdma, job); break; } /* Cancel timeout, when a buffer completes */ - if (cdma->timeout.ctx_timeout) + if (cdma->timeout.clientid) stop_cdma_timer_locked(cdma); /* Unpin the memory */ @@ -302,13 +301,13 @@ void nvhost_cdma_update_sync_queue(struct nvhost_cdma *cdma, get_restart = job->first_get; /* do CPU increments as long as this context continues */ - while (result && job->timeout == cdma->timeout.ctx_timeout) { + while (result && job->clientid == cdma->timeout.clientid) { /* different context, gets us out of this loop */ - if (job->timeout != cdma->timeout.ctx_timeout) + if (job->clientid != cdma->timeout.clientid) break; /* won't need a timeout when replayed */ - job->timeout->timeout = 0; + job->timeout = 0; syncpt_incrs = job->syncpt_end - syncpt_val; dev_dbg(dev, @@ -336,9 +335,9 @@ void nvhost_cdma_update_sync_queue(struct nvhost_cdma *cdma, /* setup GPU increments */ while (result) { /* same context, increment in the pushbuffer */ - if (job->timeout == cdma->timeout.ctx_timeout) { + if (job->clientid == cdma->timeout.clientid) { /* won't need a timeout when replayed */ - job->timeout->timeout = 0; + job->timeout = 0; /* update buffer's syncpts in the pushbuffer */ cdma_op(cdma).timeout_pb_incr(cdma, @@ -349,7 +348,7 @@ void nvhost_cdma_update_sync_queue(struct nvhost_cdma *cdma, exec_ctxsave = false; } else { - dev_warn(dev, + dev_dbg(dev, "%s: switch to a different userctx\n", __func__); /* @@ -373,7 +372,8 @@ void nvhost_cdma_update_sync_queue(struct nvhost_cdma *cdma, /* roll back DMAGET and start up channel again */ cdma_op(cdma).timeout_teardown_end(cdma, get_restart); - cdma->timeout.ctx_timeout->has_timedout = true; + if (cdma->timeout.ctx) + cdma->timeout.ctx->has_timedout = true; } /** @@ -421,33 +421,17 @@ void nvhost_cdma_deinit(struct nvhost_cdma *cdma) /** * Begin a cdma submit */ -int nvhost_cdma_begin(struct nvhost_cdma *cdma, - struct nvhost_userctx_timeout *timeout) +int nvhost_cdma_begin(struct nvhost_cdma *cdma, struct nvhost_job *job) { mutex_lock(&cdma->lock); - if (timeout && timeout->has_timedout) { - struct nvhost_master *dev = cdma_to_dev(cdma); - u32 min, max; - - min = nvhost_syncpt_update_min(&dev->syncpt, - cdma->timeout.syncpt_id); - max = nvhost_syncpt_read_min(&dev->syncpt, - cdma->timeout.syncpt_id); - - dev_dbg(&dev->pdev->dev, - "%s: skip timed out ctx submit (min = %d, max = %d)\n", - __func__, min, max); - mutex_unlock(&cdma->lock); - return -ETIMEDOUT; - } - if (timeout->timeout) { + if (job->timeout) { /* init state on first submit with timeout value */ if (!cdma->timeout.initialized) { int err; BUG_ON(!cdma_op(cdma).timeout_init); err = cdma_op(cdma).timeout_init(cdma, - timeout->syncpt_id); + job->syncpt_id); if (err) { mutex_unlock(&cdma->lock); return err; @@ -520,11 +504,8 @@ void nvhost_cdma_end(struct nvhost_cdma *cdma, cdma->first_get); /* start timer on idle -> active transitions */ - if (job->timeout->timeout && was_idle) { - cdma_start_timer_locked(cdma, - job->syncpt_id, job->syncpt_end, - job->timeout); - } + if (job->timeout && was_idle) + cdma_start_timer_locked(cdma, job); mutex_unlock(&cdma->lock); } diff --git a/drivers/video/tegra/host/nvhost_cdma.h b/drivers/video/tegra/host/nvhost_cdma.h index c8c9e168b833..87b6a14d60e3 100644 --- a/drivers/video/tegra/host/nvhost_cdma.h +++ b/drivers/video/tegra/host/nvhost_cdma.h @@ -80,7 +80,8 @@ struct buffer_timeout { u32 syncpt_val; /* syncpt value when completed */ ktime_t start_ktime; /* starting time */ /* context timeout information */ - struct nvhost_userctx_timeout *ctx_timeout; + struct nvhost_hwctx *ctx; + int clientid; }; enum cdma_event { @@ -116,8 +117,7 @@ struct nvhost_cdma { int nvhost_cdma_init(struct nvhost_cdma *cdma); void nvhost_cdma_deinit(struct nvhost_cdma *cdma); void nvhost_cdma_stop(struct nvhost_cdma *cdma); -int nvhost_cdma_begin(struct nvhost_cdma *cdma, - struct nvhost_userctx_timeout *timeout); +int nvhost_cdma_begin(struct nvhost_cdma *cdma, struct nvhost_job *job); void nvhost_cdma_push(struct nvhost_cdma *cdma, u32 op1, u32 op2); #define NVHOST_CDMA_PUSH_GATHER_CTXSAVE 0xffffffff void nvhost_cdma_push_gather(struct nvhost_cdma *cdma, diff --git a/drivers/video/tegra/host/nvhost_hwctx.h b/drivers/video/tegra/host/nvhost_hwctx.h index 6d6f458d7d75..9fbab78c8331 100644 --- a/drivers/video/tegra/host/nvhost_hwctx.h +++ b/drivers/video/tegra/host/nvhost_hwctx.h @@ -31,13 +31,11 @@ struct nvhost_channel; struct nvhost_cdma; -struct nvhost_userctx_timeout; struct nvhost_hwctx { struct kref ref; struct nvhost_channel *channel; - struct nvhost_userctx_timeout *timeout; bool valid; struct nvmap_handle_ref *save; @@ -50,6 +48,8 @@ struct nvhost_hwctx { phys_addr_t restore_phys; u32 restore_size; u32 restore_incrs; + + bool has_timedout; }; struct nvhost_hwctx_handler { diff --git a/drivers/video/tegra/host/nvhost_job.c b/drivers/video/tegra/host/nvhost_job.c index ac9c5fefa083..d0c5d731f615 100644 --- a/drivers/video/tegra/host/nvhost_job.c +++ b/drivers/video/tegra/host/nvhost_job.c @@ -121,7 +121,7 @@ static int realloc_gathers(struct nvhost_job *oldjob, static void init_fields(struct nvhost_job *job, struct nvhost_submit_hdr_ext *hdr, - int priority) + int priority, int clientid) { int num_pins = hdr ? (hdr->num_relocs + hdr->num_cmdbufs)*2 : 0; int num_waitchks = hdr ? hdr->num_waitchks : 0; @@ -137,6 +137,7 @@ static void init_fields(struct nvhost_job *job, job->syncpt_incrs = 0; job->syncpt_end = 0; job->priority = priority; + job->clientid = clientid; job->null_kickoff = false; job->first_get = 0; job->num_slots = 0; @@ -168,7 +169,7 @@ struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch, struct nvhost_submit_hdr_ext *hdr, struct nvmap_client *nvmap, int priority, - struct nvhost_userctx_timeout *timeout) + int clientid) { struct nvhost_job *job = NULL; int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0; @@ -181,14 +182,13 @@ struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch, kref_init(&job->ref); job->ch = ch; job->hwctx = hwctx; - job->timeout = timeout; job->nvmap = nvmap ? nvmap_client_get(nvmap) : NULL; err = alloc_gathers(job, num_cmdbufs); if (err) goto error; - init_fields(job, hdr, priority); + init_fields(job, hdr, priority, clientid); return job; @@ -202,7 +202,7 @@ struct nvhost_job *nvhost_job_realloc( struct nvhost_job *oldjob, struct nvhost_submit_hdr_ext *hdr, struct nvmap_client *nvmap, - int priority) + int priority, int clientid) { struct nvhost_job *newjob = NULL; int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0; @@ -223,7 +223,7 @@ struct nvhost_job *nvhost_job_realloc( nvhost_job_put(oldjob); - init_fields(newjob, hdr, priority); + init_fields(newjob, hdr, priority, clientid); return newjob; @@ -311,9 +311,9 @@ void nvhost_job_dump(struct device *dev, struct nvhost_job *job) dev_dbg(dev, " FIRST_GET 0x%x\n", job->first_get); dev_dbg(dev, " TIMEOUT %d\n", - job->timeout->timeout); - dev_dbg(dev, " TIMEOUT_CTX 0x%p\n", job->timeout); + dev_dbg(dev, " CTX 0x%p\n", + job->hwctx); dev_dbg(dev, " NUM_SLOTS %d\n", job->num_slots); dev_dbg(dev, " NUM_HANDLES %d\n", diff --git a/drivers/video/tegra/host/nvhost_job.h b/drivers/video/tegra/host/nvhost_job.h index 42e1c46d4525..d00d60f2164a 100644 --- a/drivers/video/tegra/host/nvhost_job.h +++ b/drivers/video/tegra/host/nvhost_job.h @@ -30,7 +30,6 @@ struct nvhost_hwctx; struct nvmap_client; struct nvhost_waitchk; struct nvmap_handle; -struct nvhost_userctx_timeout; /* * Each submit is tracked as a nvhost_job. @@ -44,7 +43,7 @@ struct nvhost_job { /* Hardware context valid for this client */ struct nvhost_hwctx *hwctx; - struct nvhost_userctx_timeout *timeout; + int clientid; /* Nvmap to be used for pinning & unpinning memory */ struct nvmap_client *nvmap; @@ -74,6 +73,9 @@ struct nvhost_job { /* Priority of this submit. */ int priority; + /* Maximum time to wait for this job */ + int timeout; + /* Null kickoff prevents submit from being sent to hardware */ bool null_kickoff; @@ -90,8 +92,7 @@ struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch, struct nvhost_hwctx *hwctx, struct nvhost_submit_hdr_ext *hdr, struct nvmap_client *nvmap, - int priority, - struct nvhost_userctx_timeout *timeout); + int priority, int clientid); /* * Allocate memory for a job. Just enough memory will be allocated to @@ -101,7 +102,7 @@ struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch, struct nvhost_job *nvhost_job_realloc(struct nvhost_job *oldjob, struct nvhost_submit_hdr_ext *hdr, struct nvmap_client *nvmap, - int priority); + int priority, int clientid); /* * Add a gather to a job. diff --git a/drivers/video/tegra/host/t20/cdma_t20.c b/drivers/video/tegra/host/t20/cdma_t20.c index fc2afdb26189..c034bdf90bbc 100644 --- a/drivers/video/tegra/host/t20/cdma_t20.c +++ b/drivers/video/tegra/host/t20/cdma_t20.c @@ -328,7 +328,7 @@ static void t20_cdma_timeout_pb_incr(struct nvhost_cdma *cdma, u32 getptr, struct nvhost_master *dev = cdma_to_dev(cdma); struct syncpt_buffer *sb = &cdma->syncpt_buffer; struct push_buffer *pb = &cdma->push_buffer; - struct nvhost_userctx_timeout *timeout = cdma->timeout.ctx_timeout; + struct nvhost_hwctx *hwctx = cdma->timeout.ctx; u32 getidx, *p; /* should have enough slots to incr to desired count */ @@ -337,10 +337,10 @@ static void t20_cdma_timeout_pb_incr(struct nvhost_cdma *cdma, u32 getptr, getidx = getptr - pb->phys; if (exec_ctxsave) { /* don't disrupt the CTXSAVE of a good/non-timed out ctx */ - nr_slots -= timeout->hwctx->save_slots; - syncpt_incrs -= timeout->hwctx->save_incrs; + nr_slots -= hwctx->save_slots; + syncpt_incrs -= hwctx->save_incrs; - getidx += (timeout->hwctx->save_slots * 8); + getidx += (hwctx->save_slots * 8); getidx &= (PUSH_BUFFER_SIZE - 1); dev_dbg(&dev->pdev->dev, @@ -587,9 +587,9 @@ static void t20_cdma_timeout_handler(struct work_struct *work) mutex_lock(&cdma->lock); - if (!cdma->timeout.ctx_timeout) { + if (!cdma->timeout.clientid) { dev_dbg(&dev->pdev->dev, - "cdma_timeout: expired, but has NULL context\n"); + "cdma_timeout: expired, but has no clientid\n"); mutex_unlock(&cdma->lock); return; } @@ -623,7 +623,7 @@ static void t20_cdma_timeout_handler(struct work_struct *work) __func__, cdma->timeout.syncpt_id, syncpt_op(sp).name(sp, cdma->timeout.syncpt_id), - cdma->timeout.ctx_timeout, + cdma->timeout.ctx, syncpt_val, cdma->timeout.syncpt_val); /* stop HW, resetting channel/module */ diff --git a/drivers/video/tegra/host/t20/channel_t20.c b/drivers/video/tegra/host/t20/channel_t20.c index 132bdb526bbc..6f5b1f51f11a 100644 --- a/drivers/video/tegra/host/t20/channel_t20.c +++ b/drivers/video/tegra/host/t20/channel_t20.c @@ -201,6 +201,9 @@ static int t20_channel_submit(struct nvhost_job *job) void *ctxrestore_waiter = NULL; void *ctxsave_waiter, *completed_waiter; + if (job->hwctx && job->hwctx->has_timedout) + return -ETIMEDOUT; + ctxsave_waiter = nvhost_intr_alloc_waiter(); completed_waiter = nvhost_intr_alloc_waiter(); if (!ctxsave_waiter || !completed_waiter) { @@ -252,7 +255,7 @@ static int t20_channel_submit(struct nvhost_job *job) } /* begin a CDMA submit */ - err = nvhost_cdma_begin(&channel->cdma, job->timeout); + err = nvhost_cdma_begin(&channel->cdma, job); if (err) { mutex_unlock(&channel->submitlock); nvhost_module_idle(&channel->mod); @@ -266,12 +269,12 @@ static int t20_channel_submit(struct nvhost_job *job) trace_nvhost_channel_context_switch(channel->desc->name, channel->cur_ctx, job->hwctx); hwctx_to_save = channel->cur_ctx; - if (hwctx_to_save && hwctx_to_save->timeout && - hwctx_to_save->timeout->has_timedout) { + if (hwctx_to_save && + hwctx_to_save->has_timedout) { hwctx_to_save = NULL; dev_dbg(&channel->dev->pdev->dev, "%s: skip save of timed out context (0x%p)\n", - __func__, channel->cur_ctx->timeout); + __func__, channel->cur_ctx); } if (hwctx_to_save) { job->syncpt_incrs += hwctx_to_save->save_incrs; @@ -404,7 +407,6 @@ done: static int t20_channel_read_3d_reg( struct nvhost_channel *channel, struct nvhost_hwctx *hwctx, - struct nvhost_userctx_timeout *timeout, u32 offset, u32 *value) { @@ -419,6 +421,9 @@ static int t20_channel_read_3d_reg( u32 syncval; int err; + if (hwctx && hwctx->has_timedout) + return -ETIMEDOUT; + ctx_waiter = nvhost_intr_alloc_waiter(); read_waiter = nvhost_intr_alloc_waiter(); completed_waiter = nvhost_intr_alloc_waiter(); @@ -429,7 +434,7 @@ static int t20_channel_read_3d_reg( job = nvhost_job_alloc(channel, hwctx, NULL, - channel->dev->nvmap, 0, timeout); + channel->dev->nvmap, 0, 0); if (!job) { err = -ENOMEM; goto done; @@ -468,7 +473,7 @@ static int t20_channel_read_3d_reg( job->syncpt_end = syncval; /* begin a CDMA submit */ - nvhost_cdma_begin(&channel->cdma, timeout); + nvhost_cdma_begin(&channel->cdma, job); /* push save buffer (pre-gather setup depends on unit) */ if (hwctx_to_save) diff --git a/drivers/video/tegra/host/t20/t20.c b/drivers/video/tegra/host/t20/t20.c index 605f4edf015f..e523c27a0fb0 100644 --- a/drivers/video/tegra/host/t20/t20.c +++ b/drivers/video/tegra/host/t20/t20.c @@ -95,19 +95,13 @@ int nvhost_t20_save_context(struct nvhost_module *mod, u32 syncpt_id) job = nvhost_job_alloc(ch, hwctx_to_save, NULL, - ch->dev->nvmap, 0, hwctx_to_save->timeout); + ch->dev->nvmap, 0, 0); if (IS_ERR_OR_NULL(job)) { err = PTR_ERR(job); mutex_unlock(&ch->submitlock); goto done; } - err = nvhost_cdma_begin(&ch->cdma, hwctx_to_save->timeout); - if (err) { - mutex_unlock(&ch->submitlock); - goto done; - } - hwctx_to_save->valid = true; ch->ctxhandler.get(hwctx_to_save); ch->cur_ctx = NULL; @@ -120,6 +114,12 @@ int nvhost_t20_save_context(struct nvhost_module *mod, u32 syncpt_id) job->syncpt_incrs = syncpt_incrs; job->syncpt_end = syncpt_val; + err = nvhost_cdma_begin(&ch->cdma, job); + if (err) { + mutex_unlock(&ch->submitlock); + goto done; + } + ch->ctxhandler.save_push(&ch->cdma, hwctx_to_save); nvhost_cdma_end(&ch->cdma, job); nvhost_job_put(job); |