9494 * Unlock all
9595 */
9696
97+ /*
98+ * Add validation and rebinding to the drm_exec locking loop, since both can
99+ * trigger eviction which may require sleeping dma_resv locks.
100+ */
97101static int xe_exec_fn (struct drm_gpuvm_exec * vm_exec )
98102{
99103 struct xe_vm * vm = container_of (vm_exec -> vm , struct xe_vm , gpuvm );
100- struct drm_gem_object * obj ;
101- unsigned long index ;
102- int num_fences ;
103- int ret ;
104-
105- ret = drm_gpuvm_validate (vm_exec -> vm , & vm_exec -> exec );
106- if (ret )
107- return ret ;
108-
109- /*
110- * 1 fence slot for the final submit, and 1 more for every per-tile for
111- * GPU bind and 1 extra for CPU bind. Note that there are potentially
112- * many vma per object/dma-resv, however the fence slot will just be
113- * re-used, since they are largely the same timeline and the seqno
114- * should be in order. In the case of CPU bind there is dummy fence used
115- * for all CPU binds, so no need to have a per-tile slot for that.
116- */
117- num_fences = 1 + 1 + vm -> xe -> info .tile_count ;
118104
119- /*
120- * We don't know upfront exactly how many fence slots we will need at
121- * the start of the exec, since the TTM bo_validate above can consume
122- * numerous fence slots. Also due to how the dma_resv_reserve_fences()
123- * works it only ensures that at least that many fence slots are
124- * available i.e if there are already 10 slots available and we reserve
125- * two more, it can just noop without reserving anything. With this it
126- * is quite possible that TTM steals some of the fence slots and then
127- * when it comes time to do the vma binding and final exec stage we are
128- * lacking enough fence slots, leading to some nasty BUG_ON() when
129- * adding the fences. Hence just add our own fences here, after the
130- * validate stage.
131- */
132- drm_exec_for_each_locked_object (& vm_exec -> exec , index , obj ) {
133- ret = dma_resv_reserve_fences (obj -> resv , num_fences );
134- if (ret )
135- return ret ;
136- }
137-
138- return 0 ;
105+ /* The fence slot added here is intended for the exec sched job. */
106+ return xe_vm_validate_rebind (vm , & vm_exec -> exec , 1 );
139107}
140108
141109int xe_exec_ioctl (struct drm_device * dev , void * data , struct drm_file * file )
@@ -152,7 +120,6 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
152120 struct drm_exec * exec = & vm_exec .exec ;
153121 u32 i , num_syncs = 0 , num_ufence = 0 ;
154122 struct xe_sched_job * job ;
155- struct dma_fence * rebind_fence ;
156123 struct xe_vm * vm ;
157124 bool write_locked , skip_retry = false;
158125 ktime_t end = 0 ;
@@ -290,39 +257,7 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
290257 goto err_exec ;
291258 }
292259
293- /*
294- * Rebind any invalidated userptr or evicted BOs in the VM, non-compute
295- * VM mode only.
296- */
297- rebind_fence = xe_vm_rebind (vm , false);
298- if (IS_ERR (rebind_fence )) {
299- err = PTR_ERR (rebind_fence );
300- goto err_put_job ;
301- }
302-
303- /*
304- * We store the rebind_fence in the VM so subsequent execs don't get
305- * scheduled before the rebinds of userptrs / evicted BOs is complete.
306- */
307- if (rebind_fence ) {
308- dma_fence_put (vm -> rebind_fence );
309- vm -> rebind_fence = rebind_fence ;
310- }
311- if (vm -> rebind_fence ) {
312- if (test_bit (DMA_FENCE_FLAG_SIGNALED_BIT ,
313- & vm -> rebind_fence -> flags )) {
314- dma_fence_put (vm -> rebind_fence );
315- vm -> rebind_fence = NULL ;
316- } else {
317- dma_fence_get (vm -> rebind_fence );
318- err = drm_sched_job_add_dependency (& job -> drm ,
319- vm -> rebind_fence );
320- if (err )
321- goto err_put_job ;
322- }
323- }
324-
325- /* Wait behind munmap style rebinds */
260+ /* Wait behind rebinds */
326261 if (!xe_vm_in_lr_mode (vm )) {
327262 err = drm_sched_job_add_resv_dependencies (& job -> drm ,
328263 xe_vm_resv (vm ),
0 commit comments