return 0;
}
+static inline u32 get_job_fence(struct nvhost_job *job, u32 id)
+{
+ struct nvhost_channel *ch = job->ch;
+ struct nvhost_device_data *pdata = platform_get_drvdata(ch->dev);
+ u32 fence = job->sp[id].fence;
+
+ /* take into account work done increment */
+ if (pdata->push_work_done && id == 0)
+ return fence - 1;
+
+ /* otherwise the fence is valid "as is" */
+ return fence;
+}
+
static int nvhost_ioctl_channel_submit(struct nvhost_channel_userctx *ctx,
struct nvhost_submit_args *args)
{
/* Deliver multiple fences back to the userspace */
if (fences)
for (i = 0; i < num_syncpt_incrs; ++i) {
- u32 fence = job->sp[i].fence;
+ u32 fence = get_job_fence(job, i);
err = copy_to_user(fences, &fence, sizeof(u32));
if (err)
break;
for (i = 0; i < num_syncpt_incrs; i++) {
pts[i].id = job->sp[i].id;
- pts[i].thresh = job->sp[i].fence;
+ pts[i].thresh = get_job_fence(job, i);
}
err = nvhost_sync_create_fence_fd(ctx->pdev,
if (err)
goto fail;
} else if (num_syncpt_incrs == 1)
- args->fence = job->sp[job->hwctx_syncpt_idx].fence;
+ args->fence = get_job_fence(job, job->hwctx_syncpt_idx);
else
args->fence = 0;
#include "class_ids.h"
#include "debug.h"
+static void submit_work_done_increment(struct nvhost_job *job)
+{
+ struct nvhost_channel *ch = job->ch;
+ struct nvhost_syncpt *sp = &nvhost_get_host(ch->dev)->syncpt;
+ struct nvhost_device_data *pdata = platform_get_drvdata(ch->dev);
+
+ if (!pdata->push_work_done)
+ return;
+
+ /* make the last increment at job boundary. this will ensure
+ * that the user command buffer is no longer in use */
+ job->sp[0].fence = nvhost_syncpt_incr_max(sp, job->sp[0].id, 1);
+ nvhost_cdma_push(&ch->cdma, nvhost_opcode_imm_incr_syncpt(0,
+ job->sp[0].id), NVHOST_OPCODE_NOOP);
+}
+
static void lock_device(struct nvhost_job *job, bool lock)
{
struct nvhost_channel *ch = job->ch;
submit_gathers(job);
lock_device(job, false);
+ submit_work_done_increment(job);
/* end CDMA submit & stash pinned hMems into sync queue */
nvhost_cdma_end(&ch->cdma, job);
bool exclusive; /* True if only one user at a time */
bool keepalive; /* Do not power gate when opened */
bool serialize; /* Serialize submits in the channel */
+ bool push_work_done; /* Push_op done into push buffer */
bool poweron_reset; /* Reset the engine before powerup */
bool virtual_dev; /* True if virtualized device */