static int nvhost_ioctl_channel_flush( struct nvhost_channel_userctx *ctx, struct nvhost_get_param_args *args, int null_kickoff) { struct device *device = &ctx->ch->dev->pdev->dev; int err; trace_nvhost_ioctl_channel_flush(ctx->ch->desc->name); if (!ctx->job || ctx->hdr.num_relocs || ctx->hdr.num_cmdbufs || ctx->hdr.num_waitchks) { reset_submit(ctx); dev_err(device, "channel submit out of sync\n"); return -EFAULT; } err = nvhost_job_pin(ctx->job); if (err) { dev_warn(device, "nvhost_job_pin failed: %d\n", err); return err; } if (nvhost_debug_null_kickoff_pid == current->tgid) null_kickoff = 1; ctx->job->null_kickoff = null_kickoff; if ((nvhost_debug_force_timeout_pid == current->tgid) && (nvhost_debug_force_timeout_channel == ctx->ch->chid)) { ctx->timeout = nvhost_debug_force_timeout_val; } trace_write_cmdbufs(ctx->job); /* context switch if needed, and submit user's gathers to the channel */ err = nvhost_channel_submit(ctx->job); args->value = ctx->job->syncpt_end; if (err) nvhost_job_unpin(ctx->job); return err; }
int nvhost_gr3d_t30_read_reg( struct platform_device *dev, struct nvhost_channel *channel, struct nvhost_hwctx *hwctx, u32 offset, u32 *value) { struct host1x_hwctx_handler *h = to_host1x_hwctx_handler(hwctx->h); u32 syncpt_incrs = 1; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); void *ref; void *read_waiter = NULL; struct nvhost_job *job; int err; struct mem_handle *mem = NULL; u32 *mem_ptr = NULL; u32 *cmdbuf_ptr = NULL; struct sg_table *mem_sgt = NULL; struct mem_mgr *memmgr = hwctx->memmgr; u32 opcodes[] = { /* Switch to 3D - set up output to memory */ nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0), nvhost_opcode_imm(AR3D_GLOBAL_MEMORY_OUTPUT_READS, 1), nvhost_opcode_nonincr(AR3D_DW_MEMORY_OUTPUT_ADDRESS, 1), 0xdeadbeef, /* Get host1x to request a register read */ nvhost_opcode_setclass(NV_HOST1X_CLASS_ID, host1x_uclass_indoff_r(), 1), nvhost_class_host_indoff_reg_read( host1x_uclass_indoff_indmodid_gr3d_v(), offset, false), nvhost_opcode_imm(host1x_uclass_inddata_r(), 0), /* send reg reads back to host */ nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0), nvhost_opcode_imm(AR3D_GLOBAL_MEMORY_OUTPUT_READS, 0), /* Finalize with syncpt increment */ nvhost_opcode_setclass(NV_HOST1X_CLASS_ID, host1x_uclass_incr_syncpt_base_r(), 1), nvhost_class_host_incr_syncpt_base(h->h.waitbase, 1), nvhost_opcode_imm_incr_syncpt( host1x_uclass_incr_syncpt_cond_immediate_v(), h->h.syncpt), }; /* 12 slots for gather, and one slot for storing the result value */ mem = nvhost_memmgr_alloc(memmgr, sizeof(opcodes)+4, 32, mem_mgr_flag_uncacheable); if (IS_ERR(mem)) return PTR_ERR(mem); mem_ptr = nvhost_memmgr_mmap(mem); if (!mem_ptr) { err = -ENOMEM; goto done; } cmdbuf_ptr = mem_ptr + 1; mem_sgt = nvhost_memmgr_pin(memmgr, mem, &channel->dev->dev); if (IS_ERR(mem_sgt)) { err = -ENOMEM; mem_sgt = NULL; goto done; } /* Set address of target memory slot to the stream */ opcodes[3] = sg_dma_address(mem_sgt->sgl); read_waiter = nvhost_intr_alloc_waiter(); if (!read_waiter) { err = -ENOMEM; goto done; } job = nvhost_job_alloc(channel, hwctx, 1, 0, 0, 1, memmgr); if (!job) { err = -ENOMEM; goto done; } job->hwctx_syncpt_idx = 0; job->sp->id = h->h.syncpt; job->sp->waitbase = h->h.waitbase; job->sp->incrs = syncpt_incrs; job->num_syncpts = 1; job->serialize = 1; memcpy(cmdbuf_ptr, opcodes, sizeof(opcodes)); /* Submit job */ nvhost_job_add_gather(job, nvhost_memmgr_handle_to_id(mem), ARRAY_SIZE(opcodes), 4); err = nvhost_job_pin(job, &nvhost_get_host(dev)->syncpt); if (err) goto done; err = nvhost_channel_submit(job); if (err) goto done; /* Wait for read to be ready */ err = nvhost_intr_add_action(&nvhost_get_host(dev)->intr, h->h.syncpt, job->sp->fence, NVHOST_INTR_ACTION_WAKEUP, &wq, read_waiter, &ref); read_waiter = NULL; WARN(err, "Failed to set wakeup interrupt"); wait_event(wq, nvhost_syncpt_is_expired(&nvhost_get_host(dev)->syncpt, h->h.syncpt, job->sp->fence)); nvhost_job_put(job); job = NULL; nvhost_intr_put_ref(&nvhost_get_host(dev)->intr, h->h.syncpt, ref); *value = *mem_ptr; done: kfree(read_waiter); if (mem_ptr) nvhost_memmgr_munmap(mem, mem_ptr); if (mem_sgt) nvhost_memmgr_unpin(memmgr, mem, &channel->dev->dev, mem_sgt); if (mem) nvhost_memmgr_put(memmgr, mem); return err; }