Skip to content

Commit 2e6a8a1

Browse files
robclarkRob Clark
authored andcommitted
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: Rob Clark <robdclark@chromium.org> Signed-off-by: Rob Clark <robin.clark@oss.qualcomm.com> Tested-by: Antonino Maniscalco <antomani103@gmail.com> Reviewed-by: Antonino Maniscalco <antomani103@gmail.com> Patchwork: https://patchwork.freedesktop.org/patch/661524/
1 parent ecfd9fa commit 2e6a8a1

7 files changed

Lines changed: 1205 additions & 33 deletions

File tree

drivers/gpu/drm/msm/msm_drv.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,7 @@ static const struct drm_ioctl_desc msm_ioctls[] = {
802802
DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_NEW, msm_ioctl_submitqueue_new, DRM_RENDER_ALLOW),
803803
DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_CLOSE, msm_ioctl_submitqueue_close, DRM_RENDER_ALLOW),
804804
DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_QUERY, msm_ioctl_submitqueue_query, DRM_RENDER_ALLOW),
805+
DRM_IOCTL_DEF_DRV(MSM_VM_BIND, msm_ioctl_vm_bind, DRM_RENDER_ALLOW),
805806
};
806807

807808
static void msm_show_fdinfo(struct drm_printer *p, struct drm_file *file)

drivers/gpu/drm/msm/msm_drv.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,9 @@ struct drm_gpuvm *msm_kms_init_vm(struct drm_device *dev);
255255
bool msm_use_mmu(struct drm_device *dev);
256256

257257
int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
258-
struct drm_file *file);
258+
struct drm_file *file);
259+
int msm_ioctl_vm_bind(struct drm_device *dev, void *data,
260+
struct drm_file *file);
259261

260262
#ifdef CONFIG_DEBUG_FS
261263
unsigned long msm_gem_shrinker_shrink(struct drm_device *dev, unsigned long nr_to_scan);

drivers/gpu/drm/msm/msm_gem.c

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,7 @@ static void put_pages(struct drm_gem_object *obj)
251251
}
252252
}
253253

254-
static struct page **msm_gem_get_pages_locked(struct drm_gem_object *obj,
255-
unsigned madv)
254+
struct page **msm_gem_get_pages_locked(struct drm_gem_object *obj, unsigned madv)
256255
{
257256
struct msm_gem_object *msm_obj = to_msm_bo(obj);
258257

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

10681086
if (drm_gem_is_imported(obj)) {
10691087
GEM_WARN_ON(msm_obj->vaddr);

drivers/gpu/drm/msm/msm_gem.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ struct msm_gem_vm {
7373
/** @mmu: The mmu object which manages the pgtables */
7474
struct msm_mmu *mmu;
7575

76+
/** @mmu_lock: Protects access to the mmu */
77+
struct mutex mmu_lock;
78+
7679
/**
7780
* @pid: For address spaces associated with a specific process, this
7881
* will be non-NULL:
@@ -205,6 +208,7 @@ int msm_gem_get_and_pin_iova(struct drm_gem_object *obj, struct drm_gpuvm *vm,
205208
uint64_t *iova);
206209
void msm_gem_unpin_iova(struct drm_gem_object *obj, struct drm_gpuvm *vm);
207210
void msm_gem_pin_obj_locked(struct drm_gem_object *obj);
211+
struct page **msm_gem_get_pages_locked(struct drm_gem_object *obj, unsigned madv);
208212
struct page **msm_gem_pin_pages_locked(struct drm_gem_object *obj);
209213
void msm_gem_unpin_pages_locked(struct drm_gem_object *obj);
210214
int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev,

drivers/gpu/drm/msm/msm_gem_submit.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
194194
static int submit_lookup_cmds(struct msm_gem_submit *submit,
195195
struct drm_msm_gem_submit *args, struct drm_file *file)
196196
{
197+
struct msm_context *ctx = file->driver_priv;
197198
unsigned i;
198199
size_t sz;
199200
int ret = 0;
@@ -225,6 +226,20 @@ static int submit_lookup_cmds(struct msm_gem_submit *submit,
225226
goto out;
226227
}
227228

229+
if (msm_context_is_vmbind(ctx)) {
230+
if (submit_cmd.nr_relocs) {
231+
ret = SUBMIT_ERROR(EINVAL, submit, "nr_relocs must be zero");
232+
goto out;
233+
}
234+
235+
if (submit_cmd.submit_idx || submit_cmd.submit_offset) {
236+
ret = SUBMIT_ERROR(EINVAL, submit, "submit_idx/offset must be zero");
237+
goto out;
238+
}
239+
240+
submit->cmd[i].iova = submit_cmd.iova;
241+
}
242+
228243
submit->cmd[i].type = submit_cmd.type;
229244
submit->cmd[i].size = submit_cmd.size / 4;
230245
submit->cmd[i].offset = submit_cmd.submit_offset / 4;
@@ -537,6 +552,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
537552
struct msm_syncobj_post_dep *post_deps = NULL;
538553
struct drm_syncobj **syncobjs_to_reset = NULL;
539554
struct sync_file *sync_file = NULL;
555+
unsigned cmds_to_parse;
540556
int out_fence_fd = -1;
541557
unsigned i;
542558
int ret;
@@ -661,7 +677,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
661677
if (ret)
662678
goto out;
663679

664-
for (i = 0; i < args->nr_cmds; i++) {
680+
cmds_to_parse = msm_context_is_vmbind(ctx) ? 0 : args->nr_cmds;
681+
682+
for (i = 0; i < cmds_to_parse; i++) {
665683
struct drm_gem_object *obj;
666684
uint64_t iova;
667685

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

695-
submit->nr_cmds = i;
713+
submit->nr_cmds = args->nr_cmds;
696714

697715
idr_preload(GFP_KERNEL);
698716

0 commit comments

Comments
 (0)