Пример #1
0
struct nvhost_hwctx_handler *nvhost_gr3d_t114_ctxhandler_init(
		u32 syncpt, u32 waitbase,
		struct nvhost_channel *ch)
{
	struct mem_mgr *memmgr;
	u32 *save_ptr;
	struct host1x_hwctx_handler *p;

	p = kmalloc(sizeof(*p), GFP_KERNEL);
	if (!p)
		return NULL;

	memmgr = nvhost_get_host(ch->dev)->memmgr;

	p->h.syncpt = syncpt;
	p->h.waitbase = waitbase;

	setup_save(p, NULL);

	p->save_buf = nvhost_memmgr_alloc(memmgr, p->save_size * 4, 32,
				mem_mgr_flag_write_combine);
	if (IS_ERR(p->save_buf))
		goto fail_alloc;

	save_ptr = nvhost_memmgr_mmap(p->save_buf);
	if (!save_ptr)
		goto fail_mmap;

	p->save_sgt = nvhost_memmgr_pin(memmgr, p->save_buf, &ch->dev->dev);
	if (IS_ERR(p->save_sgt))
		goto fail_pin;
	p->save_phys = sg_dma_address(p->save_sgt->sgl);

	setup_save(p, save_ptr);

	nvhost_memmgr_munmap(p->save_buf, save_ptr);

	p->save_slots = 5;
	p->h.alloc = ctx3d_alloc_v1;
	p->h.save_push = save_push_v1;
	p->h.restore_push = nvhost_3dctx_restore_push;
	p->h.save_service = NULL;
	p->h.get = nvhost_3dctx_get;
	p->h.put = nvhost_3dctx_put;

	return &p->h;

fail_pin:
	nvhost_memmgr_munmap(p->save_buf, save_ptr);
fail_mmap:
	nvhost_memmgr_put(memmgr, p->save_buf);
fail_alloc:
	kfree(p);
	return NULL;
}
Пример #2
0
int user_hwctx_set_save(struct user_hwctx *ctx,
                        ulong mem, u32 offset, u32 words, struct nvhost_reloc *reloc)
{
    struct mem_handle *buf;
    struct sg_table *sgt;
    void *page_addr;

    /* First the restore buffer is set, then the save buffer */
    if (!ctx->restore || !ctx->restore_sgt)
        return -EINVAL;

    buf = nvhost_memmgr_get(ctx->hwctx.memmgr,
                            mem, ctx->hwctx.channel->dev);
    if (IS_ERR(buf))
        return PTR_ERR(buf);

    sgt = nvhost_memmgr_pin(ctx->hwctx.memmgr, buf,
                            &ctx->hwctx.channel->dev->dev, mem_flag_none);
    if (IS_ERR(sgt))
        return PTR_ERR(sgt);

    ctx->save_offset = offset;
    ctx->save_size = words;
    ctx->save_buf = buf;
    ctx->save_sgt = sgt;

    /* Patch restore buffer address into save buffer */
    page_addr = nvhost_memmgr_kmap(ctx->save_buf,
                                   reloc->cmdbuf_offset >> PAGE_SHIFT);
    if (!page_addr)
        return -ENOMEM;

    __raw_writel(nvhost_memmgr_dma_addr(ctx->restore_sgt) + offset,
                 page_addr + (reloc->cmdbuf_offset & ~PAGE_MASK));
    nvhost_memmgr_kunmap(ctx->save_buf,
                         reloc->cmdbuf_offset >> PAGE_SHIFT,
                         page_addr);

    return 0;
}
Пример #3
0
int user_hwctx_set_restore(struct user_hwctx *ctx,
                           ulong mem, u32 offset, u32 words)
{
    struct mem_handle *buf;
    struct sg_table *sgt;

    buf = nvhost_memmgr_get(ctx->hwctx.memmgr,
                            mem, ctx->hwctx.channel->dev);
    if (IS_ERR(buf))
        return PTR_ERR(buf);

    sgt = nvhost_memmgr_pin(ctx->hwctx.memmgr, buf,
                            &ctx->hwctx.channel->dev->dev, mem_flag_none);
    if (IS_ERR(sgt))
        return PTR_ERR(sgt);

    ctx->restore_offset = offset;
    ctx->restore_size = words;
    ctx->restore = buf;
    ctx->restore_sgt = sgt;

    return 0;
}
Пример #4
0
int user_hwctx_set_restore(struct user_hwctx *ctx,
		u32 mem, u32 offset, u32 words)
{
	struct mem_handle *buf;
	struct sg_table *sgt;

	buf = nvhost_memmgr_get(ctx->hwctx.memmgr,
			mem, ctx->hwctx.channel->dev);
	if (IS_ERR_OR_NULL(buf))
		return -ENOMEM;

	sgt = nvhost_memmgr_pin(ctx->hwctx.memmgr, buf,
			&ctx->hwctx.channel->dev->dev);
	if (IS_ERR_OR_NULL(sgt))
		return -ENOMEM;

	ctx->restore_offset = offset;
	ctx->restore_size = words;
	ctx->restore = buf;
	ctx->restore_sgt = sgt;

	return 0;
}
Пример #5
0
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;
}