Merge drm/drm-next into drm-xe-next
[sfrench/cifs-2.6.git] / drivers / gpu / drm / xe / xe_exec.c
index b853feed9ccc15eefab7f0ccdf070096521e6015..59fd9bb40c1899bff6ed79a4a28a28a971fa6957 100644 (file)
 
 static int xe_exec_fn(struct drm_gpuvm_exec *vm_exec)
 {
-       return drm_gpuvm_validate(vm_exec->vm, &vm_exec->exec);
+       struct xe_vm *vm = container_of(vm_exec->vm, struct xe_vm, gpuvm);
+       struct drm_gem_object *obj;
+       unsigned long index;
+       int num_fences;
+       int ret;
+
+       ret = drm_gpuvm_validate(vm_exec->vm, &vm_exec->exec);
+       if (ret)
+               return ret;
+
+       /*
+        * 1 fence slot for the final submit, and 1 more for every per-tile for
+        * GPU bind and 1 extra for CPU bind. Note that there are potentially
+        * many vma per object/dma-resv, however the fence slot will just be
+        * re-used, since they are largely the same timeline and the seqno
+        * should be in order. In the case of CPU bind there is dummy fence used
+        * for all CPU binds, so no need to have a per-tile slot for that.
+        */
+       num_fences = 1 + 1 + vm->xe->info.tile_count;
+
+       /*
+        * We don't know upfront exactly how many fence slots we will need at
+        * the start of the exec, since the TTM bo_validate above can consume
+        * numerous fence slots. Also due to how the dma_resv_reserve_fences()
+        * works it only ensures that at least that many fence slots are
+        * available i.e if there are already 10 slots available and we reserve
+        * two more, it can just noop without reserving anything.  With this it
+        * is quite possible that TTM steals some of the fence slots and then
+        * when it comes time to do the vma binding and final exec stage we are
+        * lacking enough fence slots, leading to some nasty BUG_ON() when
+        * adding the fences. Hence just add our own fences here, after the
+        * validate stage.
+        */
+       drm_exec_for_each_locked_object(&vm_exec->exec, index, obj) {
+               ret = dma_resv_reserve_fences(obj->resv, num_fences);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
 }
 
 int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
@@ -189,7 +228,6 @@ retry:
        }
 
        vm_exec.vm = &vm->gpuvm;
-       vm_exec.num_fences = 1 + vm->xe->info.tile_count;
        vm_exec.flags = DRM_EXEC_INTERRUPTIBLE_WAIT;
        if (xe_vm_in_lr_mode(vm)) {
                drm_exec_init(exec, vm_exec.flags, 0);