video: tegra: host: Support multi-syncpt jobs
Arto Merilainen [Thu, 17 Jan 2013 07:49:13 +0000 (09:49 +0200)]
This patch adds internal structures for supporting multi-syncpoint
submits. This patch does not introduce userspace API changes.

Change-Id: I925b1e6729a57663abd06858bb569221208f19f4
Signed-off-by: Arto Merilainen <amerilainen@nvidia.com>
Reviewed-on: http://git-master/r/192061
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>

drivers/video/tegra/host/bus_client.c
drivers/video/tegra/host/gr3d/gr3d_t20.c
drivers/video/tegra/host/gr3d/gr3d_t30.c
drivers/video/tegra/host/host1x/host1x_cdma.c
drivers/video/tegra/host/host1x/host1x_channel.c
drivers/video/tegra/host/host1x/host1x_debug.c
drivers/video/tegra/host/mpe/mpe.c
drivers/video/tegra/host/nvhost_cdma.c
drivers/video/tegra/host/nvhost_cdma.h
drivers/video/tegra/host/nvhost_job.c
drivers/video/tegra/host/nvhost_job.h

index ba2397c..2177aed 100644 (file)
@@ -213,12 +213,15 @@ static int set_submit(struct nvhost_channel_userctx *ctx)
                        ctx->hdr.num_cmdbufs,
                        ctx->hdr.num_relocs,
                        ctx->hdr.num_waitchks,
+                       1,
                        ctx->memmgr);
        if (!ctx->job)
                return -ENOMEM;
        ctx->job->timeout = ctx->timeout;
-       ctx->job->syncpt_id = ctx->hdr.syncpt_id;
-       ctx->job->syncpt_incrs = ctx->hdr.syncpt_incrs;
+       ctx->job->sp->id = ctx->hdr.syncpt_id;
+       ctx->job->sp->incrs = ctx->hdr.syncpt_incrs;
+       ctx->job->hwctx_syncpt_idx = 0;
+       ctx->job->num_syncpts = 1;
        ctx->job->priority = ctx->priority;
        ctx->job->clientid = ctx->clientid;
        ctx->job->timeout_debug_dump = ctx->timeout_debug_dump;
@@ -397,7 +400,7 @@ static int nvhost_ioctl_channel_flush(
 
        /* context switch if needed, and submit user's gathers to the channel */
        err = nvhost_channel_submit(ctx->job);
-       args->value = ctx->job->syncpt_end;
+       args->value = ctx->job->sp->fence;
 
 fail:
        if (err)
@@ -433,12 +436,14 @@ static int nvhost_ioctl_channel_submit(struct nvhost_channel_userctx *ctx,
                        args->num_cmdbufs,
                        args->num_relocs,
                        args->num_waitchks,
+                       1,
                        ctx->memmgr);
        if (!job)
                return -ENOMEM;
 
        job->num_relocs = args->num_relocs;
        job->num_waitchk = args->num_waitchks;
+       job->num_syncpts = args->num_syncpt_incrs;
        job->priority = ctx->priority;
        job->clientid = ctx->clientid;
 
@@ -472,16 +477,17 @@ static int nvhost_ioctl_channel_submit(struct nvhost_channel_userctx *ctx,
                        args->syncpt_incrs, sizeof(syncpt_incr));
        if (err)
                goto fail;
-       job->syncpt_id = syncpt_incr.syncpt_id;
-       if (job->syncpt_id > host->info.nb_pts) {
+       job->sp->id = syncpt_incr.syncpt_id;
+       if (job->sp->id > host->info.nb_pts) {
                err = -EINVAL;
                goto fail;
        }
-       job->syncpt_incrs = syncpt_incr.syncpt_incrs;
+       job->sp->incrs = syncpt_incr.syncpt_incrs;
+       job->hwctx_syncpt_idx = 0;
 
        trace_nvhost_channel_submit(ctx->ch->dev->name,
                job->num_gathers, job->num_relocs, job->num_waitchk,
-               job->syncpt_id, job->syncpt_incrs);
+               job->sp->id, job->sp->incrs);
 
        err = nvhost_job_pin(job, &nvhost_get_host(ctx->ch->dev)->syncpt);
        if (err)
@@ -498,7 +504,7 @@ static int nvhost_ioctl_channel_submit(struct nvhost_channel_userctx *ctx,
        if (err)
                goto fail_submit;
 
-       args->fence = job->syncpt_end;
+       args->fence = job->sp->fence;
 
        nvhost_job_put(job);
 
index 9c39acd..e2fc34f 100644 (file)
@@ -479,14 +479,16 @@ int nvhost_gr3d_t20_read_reg(struct platform_device *dev,
                goto done;
        }
 
-       job = nvhost_job_alloc(channel, hwctx, 1, 0, 0, memmgr);
+       job = nvhost_job_alloc(channel, hwctx, 1, 0, 0, 1, memmgr);
        if (!job) {
                err = -ENOMEM;
                goto done;
        }
 
-       job->syncpt_id = h->h.syncpt;
-       job->syncpt_incrs = syncpt_incrs;
+       job->hwctx_syncpt_idx = 0;
+       job->sp->id = h->h.syncpt;
+       job->sp->incrs = syncpt_incrs;
+       job->num_syncpts = 1;
        job->serialize = 1;
        memcpy(cmdbuf_ptr, opcodes, sizeof(opcodes));
 
@@ -504,7 +506,7 @@ int nvhost_gr3d_t20_read_reg(struct platform_device *dev,
 
        /* Wait for FIFO to be ready */
        err = nvhost_intr_add_action(&nvhost_get_host(dev)->intr,
-                       h->h.syncpt, job->syncpt_end - 2,
+                       h->h.syncpt, job->sp->fence - 2,
                        NVHOST_INTR_ACTION_WAKEUP, &wq,
                        read_waiter,
                        &ref);
@@ -512,7 +514,7 @@ int nvhost_gr3d_t20_read_reg(struct platform_device *dev,
        WARN(err, "Failed to set wakeup interrupt");
        wait_event(wq,
                nvhost_syncpt_is_expired(&nvhost_get_host(dev)->syncpt,
-                               h->h.syncpt, job->syncpt_end - 2));
+                               h->h.syncpt, job->sp->fence - 2));
        nvhost_intr_put_ref(&nvhost_get_host(dev)->intr, h->h.syncpt,
                        ref);
 
index 585ff0f..ded6ae7 100644 (file)
@@ -524,14 +524,16 @@ int nvhost_gr3d_t30_read_reg(
                goto done;
        }
 
-       job = nvhost_job_alloc(channel, hwctx, 1, 0, 0, memmgr);
+       job = nvhost_job_alloc(channel, hwctx, 1, 0, 0, 1, memmgr);
        if (!job) {
                err = -ENOMEM;
                goto done;
        }
 
-       job->syncpt_id = h->h.syncpt;
-       job->syncpt_incrs = syncpt_incrs;
+       job->hwctx_syncpt_idx = 0;
+       job->sp->id = h->h.syncpt;
+       job->sp->incrs = syncpt_incrs;
+       job->num_syncpts = 1;
        job->serialize = 1;
        memcpy(cmdbuf_ptr, opcodes, sizeof(opcodes));
 
@@ -549,7 +551,7 @@ int nvhost_gr3d_t30_read_reg(
 
        /* Wait for read to be ready */
        err = nvhost_intr_add_action(&nvhost_get_host(dev)->intr,
-                       h->h.syncpt, job->syncpt_end,
+                       h->h.syncpt, job->sp->fence,
                        NVHOST_INTR_ACTION_WAKEUP, &wq,
                        read_waiter,
                        &ref);
@@ -557,7 +559,7 @@ int nvhost_gr3d_t30_read_reg(
        WARN(err, "Failed to set wakeup interrupt");
        wait_event(wq,
                nvhost_syncpt_is_expired(&nvhost_get_host(dev)->syncpt,
-                               h->h.syncpt, job->syncpt_end));
+                               h->h.syncpt, job->sp->fence));
        nvhost_job_put(job);
        job = NULL;
        nvhost_intr_put_ref(&nvhost_get_host(dev)->intr, h->h.syncpt,
index 20262e7..3ecf797 100644 (file)
@@ -448,6 +448,8 @@ static void cdma_timeout_handler(struct work_struct *work)
        struct nvhost_syncpt *sp;
        struct nvhost_channel *ch;
        int ret;
+       bool completed;
+       int i;
 
        u32 syncpt_val;
 
@@ -484,13 +486,18 @@ static void cdma_timeout_handler(struct work_struct *work)
        dev_dbg(&dev->dev->dev, "cdma_timeout: cmdproc was 0x%x is 0x%x\n",
                prev_cmdproc, cmdproc_stop);
 
-       syncpt_val = nvhost_syncpt_update_min(&dev->syncpt,
-                       cdma->timeout.syncpt_id);
+       completed = true;
+       for (i = 0; completed && i < cdma->timeout.num_syncpts; ++i) {
+               syncpt_val = nvhost_syncpt_update_min(&dev->syncpt,
+                               cdma->timeout.sp[i].id);
 
-       /* has buffer actually completed? */
-       if (nvhost_syncpt_is_expired(&dev->syncpt,
-               cdma->timeout.syncpt_id, cdma->timeout.syncpt_val)) {
+               if (!nvhost_syncpt_is_expired(&dev->syncpt,
+                       cdma->timeout.sp[i].id, cdma->timeout.sp[i].fence))
+                       completed = false;
+       }
 
+       /* has buffer actually completed? */
+       if (completed) {
                dev_dbg(&dev->dev->dev,
                         "cdma_timeout: expired, but buffer had completed\n");
                /* restore */
@@ -501,13 +508,16 @@ static void cdma_timeout_handler(struct work_struct *work)
                return;
        }
 
-       dev_warn(&dev->dev->dev,
-               "%s: timeout: %d (%s) ctx 0x%p, HW thresh %d, done %d\n",
-               __func__,
-               cdma->timeout.syncpt_id,
-               syncpt_op().name(sp, cdma->timeout.syncpt_id),
-               cdma->timeout.ctx,
-               syncpt_val, cdma->timeout.syncpt_val);
+       for (i = 0; i < cdma->timeout.num_syncpts; ++i) {
+               syncpt_val = nvhost_syncpt_read_min(&dev->syncpt,
+                               cdma->timeout.sp[i].id);
+               dev_warn(&dev->dev->dev,
+                       "%s: timeout: %d (%s) ctx 0x%p, HW thresh %d, done %d\n",
+                       __func__, cdma->timeout.sp[i].id,
+                       syncpt_op().name(sp, cdma->timeout.sp[i].id),
+                       cdma->timeout.ctx, syncpt_val,
+                       cdma->timeout.sp[i].fence);
+       }
 
        /* stop HW, resetting channel/module */
        cdma_op().timeout_teardown_begin(cdma);
index 7f406bd..ed5ffdb 100644 (file)
@@ -50,6 +50,37 @@ static void sync_waitbases(struct nvhost_channel *ch, u32 syncpt_val)
        }
 }
 
+static void serialize(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);
+       int i;
+
+       if (!job->serialize && !pdata->serialize)
+               return;
+
+       /*
+        * Force serialization by inserting a host wait for the
+        * previous job to finish before this one can commence.
+        *
+        * NOTE! This cannot be packed because otherwise we might
+        * overwrite the RESTART opcode at the end of the push
+        * buffer.
+        */
+
+       for (i = 0; i < job->num_syncpts; ++i) {
+               u32 id = job->sp[i].id;
+               u32 max = nvhost_syncpt_read_max(sp, id);
+
+               nvhost_cdma_push(&ch->cdma,
+                       nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
+                               host1x_uclass_wait_syncpt_r(), 1),
+                       nvhost_class_host_wait_syncpt(id, max));
+       }
+}
+
+
 static void *pre_submit_ctxsave(struct nvhost_job *job,
                struct nvhost_hwctx *cur_ctx)
 {
@@ -94,13 +125,15 @@ static void submit_ctxsave(struct nvhost_job *job, void *ctxsave_waiter,
        /* Retrieve save threshold if we have a waiter */
        if (ctxsave_waiter)
                save_thresh =
-                       nvhost_syncpt_read_max(&host->syncpt, job->syncpt_id)
+                       nvhost_syncpt_read_max(&host->syncpt,
+                       job->sp[job->hwctx_syncpt_idx].id)
                        + cur_ctx->save_thresh;
 
        /* Adjust the syncpoint max */
-       job->syncpt_incrs += cur_ctx->save_incrs;
+       job->sp[job->hwctx_syncpt_idx].incrs +=
+               cur_ctx->save_incrs;
        syncval = nvhost_syncpt_incr_max(&host->syncpt,
-                       job->syncpt_id,
+                       job->sp[job->hwctx_syncpt_idx].id,
                        cur_ctx->save_incrs);
 
        /* Send the save to channel */
@@ -111,7 +144,7 @@ static void submit_ctxsave(struct nvhost_job *job, void *ctxsave_waiter,
        /* Notify save service */
        if (ctxsave_waiter) {
                err = nvhost_intr_add_action(&host->intr,
-                       job->syncpt_id,
+                       job->sp[job->hwctx_syncpt_idx].id,
                        save_thresh,
                        NVHOST_INTR_ACTION_CTXSAVE, cur_ctx,
                        ctxsave_waiter,
@@ -135,9 +168,9 @@ static void submit_ctxrestore(struct nvhost_job *job)
                return;
 
        /* Increment syncpt max */
-       job->syncpt_incrs += ctx->restore_incrs;
+       job->sp[job->hwctx_syncpt_idx].incrs += ctx->restore_incrs;
        syncval = nvhost_syncpt_incr_max(&host->syncpt,
-                       job->syncpt_id,
+                       job->sp[job->hwctx_syncpt_idx].id,
                        ctx->restore_incrs);
 
        /* Send restore buffer to channel */
@@ -146,21 +179,26 @@ static void submit_ctxrestore(struct nvhost_job *job)
        trace_nvhost_channel_context_restore(ch->dev->name, ctx);
 }
 
-static void submit_nullkickoff(struct nvhost_job *job, int user_syncpt_incrs)
+static void submit_nullkickoff(struct nvhost_job *job, u32 user_syncpt_incrs)
 {
        struct nvhost_channel *ch = job->ch;
-       int incr;
+       int incr, i;
        u32 op_incr;
        struct nvhost_device_data *pdata = platform_get_drvdata(ch->dev);
 
        /* push increments that correspond to nulled out commands */
-       op_incr = nvhost_opcode_imm_incr_syncpt(
+       for (i = 0; i < job->num_syncpts; ++i) {
+               u32 incrs = (i == job->hwctx_syncpt_idx) ?
+                       user_syncpt_incrs : job->sp[i].incrs;
+               op_incr = nvhost_opcode_imm_incr_syncpt(
                        host1x_uclass_incr_syncpt_cond_op_done_v(),
-                       job->syncpt_id);
-       for (incr = 0; incr < (user_syncpt_incrs >> 1); incr++)
-               nvhost_cdma_push(&ch->cdma, op_incr, op_incr);
-       if (user_syncpt_incrs & 1)
-               nvhost_cdma_push(&ch->cdma, op_incr, NVHOST_OPCODE_NOOP);
+                       job->sp[i].id);
+               for (incr = 0; incr < (incrs >> 1); incr++)
+                       nvhost_cdma_push(&ch->cdma, op_incr, op_incr);
+               if (incrs & 1)
+                       nvhost_cdma_push(&ch->cdma, op_incr,
+                               NVHOST_OPCODE_NOOP);
+       }
 
        /* for 3d, waitbase needs to be incremented after each submit */
        if (pdata->class == NV_GRAPHICS_3D_CLASS_ID) {
@@ -172,7 +210,7 @@ static void submit_nullkickoff(struct nvhost_job *job, int user_syncpt_incrs)
                                1),
                        nvhost_class_host_incr_syncpt_base(
                                waitbase,
-                               user_syncpt_incrs));
+                               job->sp[job->hwctx_syncpt_idx].incrs));
        }
 }
 
@@ -223,28 +261,28 @@ static int host1x_channel_submit(struct nvhost_job *job)
 {
        struct nvhost_channel *ch = job->ch;
        struct nvhost_syncpt *sp = &nvhost_get_host(job->ch->dev)->syncpt;
-       u32 user_syncpt_incrs = job->syncpt_incrs;
+       u32 user_syncpt_incrs;
        u32 prev_max = 0;
-       u32 syncval;
-       int err;
-       void *completed_waiter = NULL, *ctxsave_waiter = NULL;
+       int err, i;
+       void *completed_waiters[job->num_syncpts], *ctxsave_waiter = NULL;
        struct nvhost_device_data *pdata = platform_get_drvdata(ch->dev);
+       struct nvhost_job_syncpt *hwctx_sp = job->sp + job->hwctx_syncpt_idx;
 
        /* Bail out on timed out contexts */
        if (job->hwctx && job->hwctx->has_timedout)
                return -ETIMEDOUT;
 
        /* Turn on the client module and host1x */
-       nvhost_module_busy(ch->dev);
+       for (i = 0; i < job->num_syncpts; ++i)
+               nvhost_module_busy(ch->dev);
 
        /* before error checks, return current max */
-       prev_max = job->syncpt_end =
-               nvhost_syncpt_read_max(sp, job->syncpt_id);
+       prev_max = hwctx_sp->fence = nvhost_syncpt_read_max(sp, hwctx_sp->id);
 
        /* get submit lock */
        err = mutex_lock_interruptible(&ch->submitlock);
        if (err) {
-               nvhost_module_idle(ch->dev);
+               nvhost_module_idle_mult(ch->dev, job->num_syncpts);
                goto error;
        }
 
@@ -252,47 +290,58 @@ static int host1x_channel_submit(struct nvhost_job *job)
        ctxsave_waiter = pre_submit_ctxsave(job, ch->cur_ctx);
        if (IS_ERR(ctxsave_waiter)) {
                err = PTR_ERR(ctxsave_waiter);
-               nvhost_module_idle(ch->dev);
+               nvhost_module_idle_mult(ch->dev, job->num_syncpts);
                mutex_unlock(&ch->submitlock);
                goto error;
        }
 
-       completed_waiter = nvhost_intr_alloc_waiter();
-       if (!completed_waiter) {
-               nvhost_module_idle(ch->dev);
-               mutex_unlock(&ch->submitlock);
-               err = -ENOMEM;
-               goto error;
+       for (i = 0; i < job->num_syncpts; ++i) {
+               completed_waiters[i] = nvhost_intr_alloc_waiter();
+               if (!completed_waiters[i]) {
+                       nvhost_module_idle_mult(ch->dev, job->num_syncpts);
+                       mutex_unlock(&ch->submitlock);
+                       err = -ENOMEM;
+                       goto error;
+               }
        }
 
        /* begin a CDMA submit */
        err = nvhost_cdma_begin(&ch->cdma, job);
        if (err) {
                mutex_unlock(&ch->submitlock);
-               nvhost_module_idle(ch->dev);
+               nvhost_module_idle_mult(ch->dev, job->num_syncpts);
                goto error;
        }
 
-       if (job->serialize || pdata->serialize) {
-               /* Force serialization by inserting a host wait for the
-                * previous job to finish before this one can commence. */
-               nvhost_cdma_push(&ch->cdma,
-                               nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
-                                       host1x_uclass_wait_syncpt_r(),
-                                       1),
-                               nvhost_class_host_wait_syncpt(job->syncpt_id,
-                                       nvhost_syncpt_read_max(sp,
-                                               job->syncpt_id)));
-       }
+       serialize(job);
+
+       /* submit_ctxsave() and submit_ctxrestore() use the channel syncpt */
+       user_syncpt_incrs = hwctx_sp->incrs;
 
        submit_ctxsave(job, ctxsave_waiter, ch->cur_ctx);
        submit_ctxrestore(job);
        ch->cur_ctx = job->hwctx;
 
-       syncval = nvhost_syncpt_incr_max(sp,
-                       job->syncpt_id, user_syncpt_incrs);
+       /* determine fences for all syncpoints */
+       for (i = 0; i < job->num_syncpts; ++i) {
+               u32 incrs = (i == job->hwctx_syncpt_idx) ?
+                       user_syncpt_incrs :
+                       job->sp[i].incrs;
+
+               /* create a valid max for client managed syncpoints */
+               if (nvhost_syncpt_client_managed(sp, job->sp[i].id)) {
+                       u32 min = nvhost_syncpt_read(sp, job->sp[i].id);
+                       if (min)
+                               dev_warn(&job->ch->dev->dev,
+                                       "converting an active unmanaged syncpoint %d to managed\n",
+                                       job->sp[i].id);
+                       nvhost_syncpt_set_max(sp, job->sp[i].id, min);
+                       nvhost_syncpt_set_manager(sp, job->sp[i].id, false);
+               }
 
-       job->syncpt_end = syncval;
+               job->sp[i].fence =
+                       nvhost_syncpt_incr_max(sp, job->sp[i].id, incrs);
+       }
 
        /* add a setclass for modules that require it */
        if (pdata->class)
@@ -305,30 +354,33 @@ static int host1x_channel_submit(struct nvhost_job *job)
        else
                submit_gathers(job);
 
-       sync_waitbases(ch, job->syncpt_end);
+       sync_waitbases(ch, hwctx_sp->fence);
 
        /* end CDMA submit & stash pinned hMems into sync queue */
        nvhost_cdma_end(&ch->cdma, job);
 
-       trace_nvhost_channel_submitted(ch->dev->name,
-                       prev_max, syncval);
+       trace_nvhost_channel_submitted(ch->dev->name, prev_max,
+               hwctx_sp->fence);
 
-       /* schedule a submit complete interrupt */
-       err = nvhost_intr_add_action(&nvhost_get_host(ch->dev)->intr,
-                       job->syncpt_id, syncval,
+       for (i = 0; i < job->num_syncpts; ++i) {
+               /* schedule a submit complete interrupt */
+               err = nvhost_intr_add_action(&nvhost_get_host(ch->dev)->intr,
+                       job->sp[i].id, job->sp[i].fence,
                        NVHOST_INTR_ACTION_SUBMIT_COMPLETE, ch,
-                       completed_waiter,
+                       completed_waiters[i],
                        NULL);
-       completed_waiter = NULL;
-       WARN(err, "Failed to set submit complete interrupt");
+               WARN(err, "Failed to set submit complete interrupt");
+       }
 
        mutex_unlock(&ch->submitlock);
 
        return 0;
 
 error:
+       for (i = 0; i < job->num_syncpts; ++i)
+               kfree(completed_waiters[i]);
+
        kfree(ctxsave_waiter);
-       kfree(completed_waiter);
        return err;
 }
 
@@ -400,7 +452,7 @@ static int host1x_save_context(struct nvhost_channel *ch)
                goto done;
        }
 
-       job = nvhost_job_alloc(ch, hwctx_to_save, 0, 0, 0,
+       job = nvhost_job_alloc(ch, hwctx_to_save, 0, 0, 0, 1,
                        nvhost_get_host(ch->dev)->memmgr);
        if (!job) {
                err = -ENOMEM;
@@ -416,9 +468,11 @@ static int host1x_save_context(struct nvhost_channel *ch)
        syncpt_val = nvhost_syncpt_incr_max(&nvhost_get_host(ch->dev)->syncpt,
                                        syncpt_id, syncpt_incrs);
 
-       job->syncpt_id = syncpt_id;
-       job->syncpt_incrs = syncpt_incrs;
-       job->syncpt_end = syncpt_val;
+       job->hwctx_syncpt_idx = 0;
+       job->sp->id = syncpt_id;
+       job->sp->incrs = syncpt_incrs;
+       job->sp->fence = syncpt_val;
+       job->num_syncpts = 1;
 
        err = nvhost_cdma_begin(&ch->cdma, job);
        if (err) {
index 4cb9464..ffa8970 100644 (file)
@@ -76,8 +76,8 @@ static void show_channel_gathers(struct output *o, struct nvhost_cdma *cdma)
                        " first_get=%08x, timeout=%d, ctx=%p,"
                        " num_slots=%d, num_handles=%d\n",
                        job,
-                       job->syncpt_id,
-                       job->syncpt_end,
+                       job->sp ? job->sp->id : -1,
+                       job->sp ? job->sp->fence : -1,
                        job->first_get,
                        job->timeout,
                        job->hwctx,
index ff06060..75b697c 100644 (file)
@@ -805,14 +805,16 @@ int nvhost_mpe_read_reg(struct platform_device *dev,
                goto done;
        }
 
-       job = nvhost_job_alloc(channel, hwctx, 1, 0, 0, memmgr);
+       job = nvhost_job_alloc(channel, hwctx, 1, 0, 0, 1, memmgr);
        if (!job) {
                err = -ENOMEM;
                goto done;
        }
 
-       job->syncpt_id = h->h.syncpt;
-       job->syncpt_incrs = syncpt_incrs;
+       job->hwctx_syncpt_idx = 0;
+       job->sp->id = h->h.syncpt;
+       job->sp->incrs = syncpt_incrs;
+       job->num_syncpts = 1;
        job->serialize = 1;
        memcpy(cmdbuf_ptr, opcodes, sizeof(opcodes));
 
@@ -830,7 +832,7 @@ int nvhost_mpe_read_reg(struct platform_device *dev,
 
        /* Wait for FIFO to be ready */
        err = nvhost_intr_add_action(&nvhost_get_host(dev)->intr,
-                       h->h.syncpt, job->syncpt_end - 2,
+                       h->h.syncpt, job->sp->fence - 2,
                        NVHOST_INTR_ACTION_WAKEUP, &wq,
                        read_waiter,
                        &ref);
@@ -838,7 +840,7 @@ int nvhost_mpe_read_reg(struct platform_device *dev,
        WARN(err, "Failed to set wakeup interrupt");
        wait_event(wq,
                nvhost_syncpt_is_expired(&nvhost_get_host(dev)->syncpt,
-                               h->h.syncpt, job->syncpt_end - 2));
+                               h->h.syncpt, job->sp->fence - 2));
        nvhost_intr_put_ref(&nvhost_get_host(dev)->intr, h->h.syncpt,
                        ref);
 
index d6182c8..9dd508c 100644 (file)
@@ -49,11 +49,6 @@ static void add_to_sync_queue(struct nvhost_cdma *cdma,
                              u32 nr_slots,
                              u32 first_get)
 {
-       if (job->syncpt_id == NVSYNCPT_INVALID) {
-               dev_warn(&job->ch->dev->dev, "%s: Invalid syncpt\n",
-                               __func__);
-               return;
-       }
        job->first_get = first_get;
        job->num_slots = nr_slots;
        nvhost_job_get(job);
@@ -142,8 +137,8 @@ static void cdma_start_timer_locked(struct nvhost_cdma *cdma,
 
        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.sp = job->sp;
+       cdma->timeout.num_syncpts = job->num_syncpts;
        cdma->timeout.start_ktime = ktime_get();
        cdma->timeout.timeout_debug_dump = job->timeout_debug_dump;
 
@@ -191,9 +186,15 @@ static void update_cdma_locked(struct nvhost_cdma *cdma)
         * to consume as many sync queue entries as possible without blocking
         */
        list_for_each_entry_safe(job, n, &cdma->sync_queue, list) {
+               bool completed = true;
+               int i;
+
                /* Check whether this syncpt has completed, and bail if not */
-               if (!nvhost_syncpt_is_expired(sp,
-                               job->syncpt_id, job->syncpt_end)) {
+               for (i = 0; completed && i < job->num_syncpts; ++i)
+                       completed &= nvhost_syncpt_is_expired(sp,
+                               job->sp[i].id, job->sp[i].fence);
+
+               if (!completed) {
                        /* Start timer on next pending syncpt */
                        if (job->timeout)
                                cdma_start_timer_locked(cdma, job);
@@ -243,20 +244,33 @@ static void update_cdma_locked(struct nvhost_cdma *cdma)
        }
 }
 
+
+static void nvhost_cdma_finalize_job_incrs(struct nvhost_syncpt *syncpt,
+                                       struct nvhost_job_syncpt *sp)
+{
+       u32 id = sp->id;
+       u32 fence = sp->fence;
+       u32 syncpt_val = nvhost_syncpt_read_min(syncpt, id);
+       u32 syncpt_incrs = fence - syncpt_val;
+
+       /* do CPU increments */
+       while (syncpt_incrs--)
+               nvhost_syncpt_cpu_incr(syncpt, id);
+
+       /* ensure shadow is up to date */
+       nvhost_syncpt_update_min(syncpt, id);
+}
+
 void nvhost_cdma_update_sync_queue(struct nvhost_cdma *cdma,
                struct nvhost_syncpt *syncpt, struct platform_device *dev)
 {
        u32 get_restart;
-       u32 syncpt_incrs;
        struct nvhost_job *job = NULL;
-       u32 syncpt_val;
        struct nvhost_device_data *pdata = platform_get_drvdata(dev);
+       int nb_pts = nvhost_syncpt_nb_pts(syncpt);
+       DECLARE_BITMAP(syncpt_used, nb_pts);
 
-       syncpt_val = nvhost_syncpt_update_min(syncpt, cdma->timeout.syncpt_id);
-
-       dev_dbg(&dev->dev,
-               "%s: starting cleanup (thresh %d)\n",
-               __func__, syncpt_val);
+       bitmap_zero(syncpt_used, nb_pts);
 
        /*
         * Move the sync_queue read pointer to the first entry that hasn't
@@ -270,13 +284,23 @@ void nvhost_cdma_update_sync_queue(struct nvhost_cdma *cdma,
                __func__);
 
        list_for_each_entry(job, &cdma->sync_queue, list) {
-               if (!nvhost_syncpt_is_expired(syncpt,
-                       cdma->timeout.syncpt_id, job->syncpt_end))
-                       break;
+               int i;
+               for (i = 0; i < job->num_syncpts; ++i) {
+                       u32 id = cdma->timeout.sp[i].id;
+
+                       if (!test_bit(id, syncpt_used))
+                               nvhost_syncpt_update_min(syncpt, id);
+
+                       set_bit(id, syncpt_used);
+
+                       if (!nvhost_syncpt_is_expired(syncpt, id,
+                               job->sp[i].fence))
+                               goto out;
+               }
 
                nvhost_job_dump(&dev->dev, job);
        }
-
+out:
        /*
         * Walk the sync_queue, first incrementing with the CPU syncpts that
         * are partially executed (the first buffer) or fully skipped while
@@ -313,30 +337,22 @@ void nvhost_cdma_update_sync_queue(struct nvhost_cdma *cdma,
                /* won't need a timeout when replayed */
                job->timeout = 0;
 
-               syncpt_incrs = job->syncpt_end - syncpt_val;
-               dev_dbg(&dev->dev,
-                       "%s: CPU incr (%d)\n", __func__, syncpt_incrs);
-
-               /* do CPU increments */
-               for (i = 0; i < syncpt_incrs; i++)
-                       nvhost_syncpt_cpu_incr(&cdma_to_dev(cdma)->syncpt,
-                               cdma->timeout.syncpt_id);
+               for (i = 0; i < job->num_syncpts; ++i)
+                       nvhost_cdma_finalize_job_incrs(syncpt, job->sp + i);
 
-               /* ensure shadow is up to date */
-               nvhost_syncpt_update_min(&cdma_to_dev(cdma)->syncpt,
-                       cdma->timeout.syncpt_id);
+               /* synchronize wait base. only the channel syncpoint wait base
+                * is maintained */
+               if (job->sp[job->hwctx_syncpt_idx].id != NVSYNCPT_2D_0 &&
+                       pdata->waitbases[0]) {
 
-               /* synchronize wait bases */
-               if (cdma->timeout.syncpt_id != NVSYNCPT_2D_0 &&
-                       pdata->waitbases[0])
                        nvhost_syncpt_cpu_set_wait_base(dev,
-                               pdata->waitbases[0], job->syncpt_end);
+                               pdata->waitbases[0],
+                               job->sp[job->hwctx_syncpt_idx].fence);
+               }
 
                /* cleanup push buffer */
                cdma_op().timeout_pb_cleanup(cdma, job->first_get,
                        job->num_slots);
-
-               syncpt_val += syncpt_incrs;
        }
 
        list_for_each_entry_from(job, &cdma->sync_queue, list)
@@ -399,7 +415,7 @@ int nvhost_cdma_begin(struct nvhost_cdma *cdma, struct nvhost_job *job)
                if (!cdma->timeout.initialized) {
                        int err;
                        err = cdma_op().timeout_init(cdma,
-                               job->syncpt_id);
+                               job->sp->id);
                        if (err) {
                                mutex_unlock(&cdma->lock);
                                return err;
index de3a85a..4b6dca2 100644 (file)
@@ -65,13 +65,13 @@ struct push_buffer {
 struct buffer_timeout {
        struct delayed_work wq;         /* work queue */
        bool initialized;               /* timer one-time setup flag */
-       u32 syncpt_id;                  /* buffer completion syncpt id */
-       u32 syncpt_val;                 /* syncpt value when completed */
+       struct nvhost_job_syncpt *sp;   /* buffer syncpoint information */
        ktime_t start_ktime;            /* starting time */
        /* context timeout information */
        struct nvhost_hwctx *ctx;
        int clientid;
        bool timeout_debug_dump;
+       int num_syncpts;
 };
 
 enum cdma_event {
index 778bb2e..cacbb2e 100644 (file)
@@ -35,7 +35,8 @@
 /* Magic to use to fill freed handle slots */
 #define BAD_MAGIC 0xdeadbeef
 
-static size_t job_size(u32 num_cmdbufs, u32 num_relocs, u32 num_waitchks)
+static size_t job_size(u32 num_cmdbufs, u32 num_relocs, u32 num_waitchks,
+                       u32 num_syncpts)
 {
        s64 num_unpins = num_cmdbufs + num_relocs;
        s64 total;
@@ -47,7 +48,8 @@ static size_t job_size(u32 num_cmdbufs, u32 num_relocs, u32 num_waitchks)
                        + num_waitchks * sizeof(struct nvhost_waitchk)
                        + num_cmdbufs * sizeof(struct nvhost_job_gather)
                        + num_unpins * sizeof(dma_addr_t)
-                       + num_unpins * sizeof(u32 *);
+                       + num_unpins * sizeof(u32 *)
+                       + num_syncpts * sizeof(struct nvhost_job_syncpt);
 
        if(total > ULONG_MAX)
                return 0;
@@ -56,7 +58,8 @@ static size_t job_size(u32 num_cmdbufs, u32 num_relocs, u32 num_waitchks)
 
 
 static void init_fields(struct nvhost_job *job,
-               u32 num_cmdbufs, u32 num_relocs, u32 num_waitchks)
+               u32 num_cmdbufs, u32 num_relocs, u32 num_waitchks,
+               u32 num_syncpts)
 {
        int num_unpins = num_cmdbufs + num_relocs;
        void *mem = job;
@@ -82,6 +85,8 @@ static void init_fields(struct nvhost_job *job,
        job->addr_phys = num_unpins ? mem : NULL;
        mem += num_unpins * sizeof(dma_addr_t);
        job->pin_ids = num_unpins ? mem : NULL;
+       mem += num_unpins * sizeof(u32 *);
+       job->sp = num_syncpts ? mem : NULL;
 
        job->reloc_addr_phys = job->addr_phys;
        job->gather_addr_phys = &job->addr_phys[num_relocs];
@@ -90,10 +95,11 @@ static void init_fields(struct nvhost_job *job,
 struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch,
                struct nvhost_hwctx *hwctx,
                int num_cmdbufs, int num_relocs, int num_waitchks,
-               struct mem_mgr *memmgr)
+               int num_syncpts, struct mem_mgr *memmgr)
 {
        struct nvhost_job *job = NULL;
-       size_t size = job_size(num_cmdbufs, num_relocs, num_waitchks);
+       size_t size =
+               job_size(num_cmdbufs, num_relocs, num_waitchks, num_syncpts);
 
        if(!size)
                return NULL;
@@ -108,7 +114,7 @@ struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch,
                hwctx->h->get(hwctx);
        job->memmgr = memmgr ? nvhost_memmgr_get_mgr(memmgr) : NULL;
 
-       init_fields(job, num_cmdbufs, num_relocs, num_waitchks);
+       init_fields(job, num_cmdbufs, num_relocs, num_waitchks, num_syncpts);
 
        return job;
 }
@@ -399,9 +405,9 @@ void nvhost_job_unpin(struct nvhost_job *job)
 void nvhost_job_dump(struct device *dev, struct nvhost_job *job)
 {
        dev_info(dev, "    SYNCPT_ID   %d\n",
-               job->syncpt_id);
+               job->sp->id);
        dev_info(dev, "    SYNCPT_VAL  %d\n",
-               job->syncpt_end);
+               job->sp->fence);
        dev_info(dev, "    FIRST_GET   0x%x\n",
                job->first_get);
        dev_info(dev, "    TIMEOUT     %d\n",
index d3745a0..b222d86 100644 (file)
@@ -39,6 +39,12 @@ struct nvhost_job_gather {
        struct mem_handle *ref;
 };
 
+struct nvhost_job_syncpt {
+       u32 id;
+       u32 incrs;
+       u32 fence;
+};
+
 /*
  * Each submit is tracked as a nvhost_job.
  */
@@ -80,9 +86,11 @@ struct nvhost_job {
        dma_addr_t *reloc_addr_phys;
 
        /* Sync point id, number of increments and end related to the submit */
-       u32 syncpt_id;
-       u32 syncpt_incrs;
-       u32 syncpt_end;
+       struct nvhost_job_syncpt *sp;
+       int num_syncpts;
+
+       /* Hold number to the "stream syncpoint" index */
+       int hwctx_syncpt_idx;
 
        /* Priority of this submit. */
        int priority;
@@ -114,7 +122,7 @@ struct nvhost_job {
 struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch,
                struct nvhost_hwctx *hwctx,
                int num_cmdbufs, int num_relocs, int num_waitchks,
-               struct mem_mgr *memmgr);
+               int num_syncpts, struct mem_mgr *memmgr);
 
 /*
  * Add a gather to a job.