44 * Author: Rob Clark <robdclark@gmail.com>
55 */
66
7+ #include <linux/dma-fence-unwrap.h>
78#include <linux/file.h>
89#include <linux/sync_file.h>
910#include <linux/uaccess.h>
@@ -259,29 +260,47 @@ static int submit_lookup_cmds(struct msm_gem_submit *submit,
259260static int submit_lock_objects (struct msm_gem_submit * submit )
260261{
261262 unsigned flags = DRM_EXEC_INTERRUPTIBLE_WAIT ;
263+ struct drm_exec * exec = & submit -> exec ;
262264 int ret ;
263265
266+ if (msm_context_is_vmbind (submit -> queue -> ctx )) {
267+ flags |= DRM_EXEC_IGNORE_DUPLICATES ;
268+
269+ drm_exec_init (& submit -> exec , flags , submit -> nr_bos );
270+
271+ drm_exec_until_all_locked (& submit -> exec ) {
272+ ret = drm_gpuvm_prepare_vm (submit -> vm , exec , 1 );
273+ drm_exec_retry_on_contention (exec );
274+ if (ret )
275+ return ret ;
276+
277+ ret = drm_gpuvm_prepare_objects (submit -> vm , exec , 1 );
278+ drm_exec_retry_on_contention (exec );
279+ if (ret )
280+ return ret ;
281+ }
282+
283+ return 0 ;
284+ }
285+
264286 drm_exec_init (& submit -> exec , flags , submit -> nr_bos );
265287
266288 drm_exec_until_all_locked (& submit -> exec ) {
267289 ret = drm_exec_lock_obj (& submit -> exec ,
268290 drm_gpuvm_resv_obj (submit -> vm ));
269291 drm_exec_retry_on_contention (& submit -> exec );
270292 if (ret )
271- goto error ;
293+ return ret ;
272294 for (unsigned i = 0 ; i < submit -> nr_bos ; i ++ ) {
273295 struct drm_gem_object * obj = submit -> bos [i ].obj ;
274296 ret = drm_exec_prepare_obj (& submit -> exec , obj , 1 );
275297 drm_exec_retry_on_contention (& submit -> exec );
276298 if (ret )
277- goto error ;
299+ return ret ;
278300 }
279301 }
280302
281303 return 0 ;
282-
283- error :
284- return ret ;
285304}
286305
287306static int submit_fence_sync (struct msm_gem_submit * submit )
@@ -367,9 +386,18 @@ static void submit_unpin_objects(struct msm_gem_submit *submit)
367386
368387static void submit_attach_object_fences (struct msm_gem_submit * submit )
369388{
370- int i ;
389+ struct msm_gem_vm * vm = to_msm_vm (submit -> vm );
390+ struct dma_fence * last_fence ;
391+
392+ if (msm_context_is_vmbind (submit -> queue -> ctx )) {
393+ drm_gpuvm_resv_add_fence (submit -> vm , & submit -> exec ,
394+ submit -> user_fence ,
395+ DMA_RESV_USAGE_BOOKKEEP ,
396+ DMA_RESV_USAGE_BOOKKEEP );
397+ return ;
398+ }
371399
372- for (i = 0 ; i < submit -> nr_bos ; i ++ ) {
400+ for (unsigned i = 0 ; i < submit -> nr_bos ; i ++ ) {
373401 struct drm_gem_object * obj = submit -> bos [i ].obj ;
374402
375403 if (submit -> bos [i ].flags & MSM_SUBMIT_BO_WRITE )
@@ -379,6 +407,10 @@ static void submit_attach_object_fences(struct msm_gem_submit *submit)
379407 dma_resv_add_fence (obj -> resv , submit -> user_fence ,
380408 DMA_RESV_USAGE_READ );
381409 }
410+
411+ last_fence = vm -> last_fence ;
412+ vm -> last_fence = dma_fence_unwrap_merge (submit -> user_fence , last_fence );
413+ dma_fence_put (last_fence );
382414}
383415
384416static int submit_bo (struct msm_gem_submit * submit , uint32_t idx ,
@@ -537,6 +569,11 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
537569 if (!queue )
538570 return - ENOENT ;
539571
572+ if (queue -> flags & MSM_SUBMITQUEUE_VM_BIND ) {
573+ ret = UERR (EINVAL , dev , "Invalid queue type" );
574+ goto out_post_unlock ;
575+ }
576+
540577 ring = gpu -> rb [queue -> ring_nr ];
541578
542579 if (args -> flags & MSM_SUBMIT_FENCE_FD_OUT ) {
@@ -727,6 +764,18 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
727764
728765 submit_attach_object_fences (submit );
729766
767+ if (msm_context_is_vmbind (ctx )) {
768+ /*
769+ * If we are not using VM_BIND, submit_pin_vmas() will validate
770+ * just the BOs attached to the submit. In that case we don't
771+ * need to validate the _entire_ vm, because userspace tracked
772+ * what BOs are associated with the submit.
773+ */
774+ ret = drm_gpuvm_validate (submit -> vm , & submit -> exec );
775+ if (ret )
776+ goto out ;
777+ }
778+
730779 /* The scheduler owns a ref now: */
731780 msm_gem_submit_get (submit );
732781
0 commit comments