Commit 2e6a8a1f authored by Rob Clark's avatar Rob Clark
Browse files

drm/msm: Add VM_BIND ioctl



Add a VM_BIND ioctl for binding/unbinding buffers into a VM.  This is
only supported if userspace has opted in to MSM_PARAM_EN_VM_BIND.

Signed-off-by: default avatarRob Clark <robdclark@chromium.org>
Signed-off-by: default avatarRob Clark <robin.clark@oss.qualcomm.com>
Tested-by: default avatarAntonino Maniscalco <antomani103@gmail.com>
Reviewed-by: default avatarAntonino Maniscalco <antomani103@gmail.com>
Patchwork: https://patchwork.freedesktop.org/patch/661524/
parent ecfd9fa8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -802,6 +802,7 @@ static const struct drm_ioctl_desc msm_ioctls[] = {
	DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_NEW,   msm_ioctl_submitqueue_new,   DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_CLOSE, msm_ioctl_submitqueue_close, DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_QUERY, msm_ioctl_submitqueue_query, DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(MSM_VM_BIND,      msm_ioctl_vm_bind,      DRM_RENDER_ALLOW),
};

static void msm_show_fdinfo(struct drm_printer *p, struct drm_file *file)
+3 −1
Original line number Diff line number Diff line
@@ -256,6 +256,8 @@ bool msm_use_mmu(struct drm_device *dev);

int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
			 struct drm_file *file);
int msm_ioctl_vm_bind(struct drm_device *dev, void *data,
		      struct drm_file *file);

#ifdef CONFIG_DEBUG_FS
unsigned long msm_gem_shrinker_shrink(struct drm_device *dev, unsigned long nr_to_scan);
+29 −11
Original line number Diff line number Diff line
@@ -251,8 +251,7 @@ static void put_pages(struct drm_gem_object *obj)
	}
}

static struct page **msm_gem_get_pages_locked(struct drm_gem_object *obj,
					      unsigned madv)
struct page **msm_gem_get_pages_locked(struct drm_gem_object *obj, unsigned madv)
{
	struct msm_gem_object *msm_obj = to_msm_bo(obj);

@@ -1052,18 +1051,37 @@ static void msm_gem_free_object(struct drm_gem_object *obj)
	/*
	 * We need to lock any VMs the object is still attached to, but not
	 * the object itself (see explaination in msm_gem_assert_locked()),
	 * so just open-code this special case:
	 * so just open-code this special case.
	 *
	 * Note that we skip the dance if we aren't attached to any VM.  This
	 * is load bearing.  The driver needs to support two usage models:
	 *
	 * 1. Legacy kernel managed VM: Userspace expects the VMA's to be
	 *    implicitly torn down when the object is freed, the VMA's do
	 *    not hold a hard reference to the BO.
	 *
	 * 2. VM_BIND, userspace managed VM: The VMA holds a reference to the
	 *    BO.  This can be dropped when the VM is closed and it's associated
	 *    VMAs are torn down.  (See msm_gem_vm_close()).
	 *
	 * In the latter case the last reference to a BO can be dropped while
	 * we already have the VM locked.  It would have already been removed
	 * from the gpuva list, but lockdep doesn't know that.  Or understand
	 * the differences between the two usage models.
	 */
	if (!list_empty(&obj->gpuva.list)) {
		drm_exec_init(&exec, 0, 0);
		drm_exec_until_all_locked (&exec) {
			struct drm_gpuvm_bo *vm_bo;
			drm_gem_for_each_gpuvm_bo (vm_bo, obj) {
			drm_exec_lock_obj(&exec, drm_gpuvm_resv_obj(vm_bo->vm));
				drm_exec_lock_obj(&exec,
						  drm_gpuvm_resv_obj(vm_bo->vm));
				drm_exec_retry_on_contention(&exec);
			}
		}
		put_iova_spaces(obj, NULL, true);
		drm_exec_fini(&exec);     /* drop locks */
	}

	if (drm_gem_is_imported(obj)) {
		GEM_WARN_ON(msm_obj->vaddr);
+4 −0
Original line number Diff line number Diff line
@@ -73,6 +73,9 @@ struct msm_gem_vm {
	/** @mmu: The mmu object which manages the pgtables */
	struct msm_mmu *mmu;

	/** @mmu_lock: Protects access to the mmu */
	struct mutex mmu_lock;

	/**
	 * @pid: For address spaces associated with a specific process, this
	 * will be non-NULL:
@@ -205,6 +208,7 @@ int msm_gem_get_and_pin_iova(struct drm_gem_object *obj, struct drm_gpuvm *vm,
			     uint64_t *iova);
void msm_gem_unpin_iova(struct drm_gem_object *obj, struct drm_gpuvm *vm);
void msm_gem_pin_obj_locked(struct drm_gem_object *obj);
struct page **msm_gem_get_pages_locked(struct drm_gem_object *obj, unsigned madv);
struct page **msm_gem_pin_pages_locked(struct drm_gem_object *obj);
void msm_gem_unpin_pages_locked(struct drm_gem_object *obj);
int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
+20 −2
Original line number Diff line number Diff line
@@ -194,6 +194,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
static int submit_lookup_cmds(struct msm_gem_submit *submit,
		struct drm_msm_gem_submit *args, struct drm_file *file)
{
	struct msm_context *ctx = file->driver_priv;
	unsigned i;
	size_t sz;
	int ret = 0;
@@ -225,6 +226,20 @@ static int submit_lookup_cmds(struct msm_gem_submit *submit,
			goto out;
		}

		if (msm_context_is_vmbind(ctx)) {
			if (submit_cmd.nr_relocs) {
				ret = SUBMIT_ERROR(EINVAL, submit, "nr_relocs must be zero");
				goto out;
			}

			if (submit_cmd.submit_idx || submit_cmd.submit_offset) {
				ret = SUBMIT_ERROR(EINVAL, submit, "submit_idx/offset must be zero");
				goto out;
			}

			submit->cmd[i].iova = submit_cmd.iova;
		}

		submit->cmd[i].type = submit_cmd.type;
		submit->cmd[i].size = submit_cmd.size / 4;
		submit->cmd[i].offset = submit_cmd.submit_offset / 4;
@@ -537,6 +552,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
	struct msm_syncobj_post_dep *post_deps = NULL;
	struct drm_syncobj **syncobjs_to_reset = NULL;
	struct sync_file *sync_file = NULL;
	unsigned cmds_to_parse;
	int out_fence_fd = -1;
	unsigned i;
	int ret;
@@ -661,7 +677,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
	if (ret)
		goto out;

	for (i = 0; i < args->nr_cmds; i++) {
	cmds_to_parse = msm_context_is_vmbind(ctx) ? 0 : args->nr_cmds;

	for (i = 0; i < cmds_to_parse; i++) {
		struct drm_gem_object *obj;
		uint64_t iova;

@@ -692,7 +710,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
			goto out;
	}

	submit->nr_cmds = i;
	submit->nr_cmds = args->nr_cmds;

	idr_preload(GFP_KERNEL);

Loading