Commit fe2f3b1c authored by Rob Clark's avatar Rob Clark
Browse files

drm/msm: Handle in-place remaps



Detect and handle the special case of a MAP op simply updating the vma
flags of an existing vma, and skip the pgtable updates.  This allows
turnip to set the MSM_VMA_DUMP flag on an existing mapping without
requiring additional synchronization against commands running on the
GPU.

Signed-off-by: default avatarRob Clark <robin.clark@oss.qualcomm.com>
Tested-by: default avatarConnor Abbott <cwabbott0@gmail.com>
Patchwork: https://patchwork.freedesktop.org/patch/667238/
parent ba3afade
Loading
Loading
Loading
Loading
+37 −4
Original line number Diff line number Diff line
@@ -451,6 +451,8 @@ msm_gem_vm_bo_validate(struct drm_gpuvm_bo *vm_bo, struct drm_exec *exec)
struct op_arg {
	unsigned flags;
	struct msm_vm_bind_job *job;
	const struct msm_vm_bind_op *op;
	bool kept;
};

static void
@@ -472,14 +474,18 @@ vma_from_op(struct op_arg *arg, struct drm_gpuva_op_map *op)
}

static int
msm_gem_vm_sm_step_map(struct drm_gpuva_op *op, void *arg)
msm_gem_vm_sm_step_map(struct drm_gpuva_op *op, void *_arg)
{
	struct msm_vm_bind_job *job = ((struct op_arg *)arg)->job;
	struct op_arg *arg = _arg;
	struct msm_vm_bind_job *job = arg->job;
	struct drm_gem_object *obj = op->map.gem.obj;
	struct drm_gpuva *vma;
	struct sg_table *sgt;
	unsigned prot;

	if (arg->kept)
		return 0;

	vma = vma_from_op(arg, &op->map);
	if (WARN_ON(IS_ERR(vma)))
		return PTR_ERR(vma);
@@ -599,15 +605,41 @@ msm_gem_vm_sm_step_remap(struct drm_gpuva_op *op, void *arg)
}

static int
msm_gem_vm_sm_step_unmap(struct drm_gpuva_op *op, void *arg)
msm_gem_vm_sm_step_unmap(struct drm_gpuva_op *op, void *_arg)
{
	struct msm_vm_bind_job *job = ((struct op_arg *)arg)->job;
	struct op_arg *arg = _arg;
	struct msm_vm_bind_job *job = arg->job;
	struct drm_gpuva *vma = op->unmap.va;
	struct msm_gem_vma *msm_vma = to_msm_vma(vma);

	vm_dbg("%p:%p:%p: %016llx %016llx", vma->vm, vma, vma->gem.obj,
	       vma->va.addr, vma->va.range);

	/*
	 * Detect in-place remap.  Turnip does this to change the vma flags,
	 * in particular MSM_VMA_DUMP.  In this case we want to avoid actually
	 * touching the page tables, as that would require synchronization
	 * against SUBMIT jobs running on the GPU.
	 */
	if (op->unmap.keep &&
	    (arg->op->op == MSM_VM_BIND_OP_MAP) &&
	    (vma->gem.obj == arg->op->obj) &&
	    (vma->gem.offset == arg->op->obj_offset) &&
	    (vma->va.addr == arg->op->iova) &&
	    (vma->va.range == arg->op->range)) {
		/* We are only expecting a single in-place unmap+map cb pair: */
		WARN_ON(arg->kept);

		/* Leave the existing VMA in place, but signal that to the map cb: */
		arg->kept = true;

		/* Only flags are changing, so update that in-place: */
		unsigned orig_flags = vma->flags & (DRM_GPUVA_USERBITS - 1);
		vma->flags = orig_flags | arg->flags;

		return 0;
	}

	if (!msm_vma->mapped)
		goto out_close;

@@ -1268,6 +1300,7 @@ vm_bind_job_prepare(struct msm_vm_bind_job *job)
		const struct msm_vm_bind_op *op = &job->ops[i];
		struct op_arg arg = {
			.job = job,
			.op = op,
		};

		switch (op->op) {