33 * Copyright © 2021 Intel Corporation
44 */
55
6- #include <linux/dma-fence-array.h>
7-
86#include <drm/ttm/ttm_bo_driver.h>
97
108#include "i915_drv.h"
@@ -44,17 +42,12 @@ void i915_ttm_migrate_set_failure_modes(bool gpu_migration,
4442#endif
4543
4644/**
47- * DOC: Set of utilities to dynamically collect dependencies and
48- * eventually coalesce them into a single fence which is fed into
49- * the GT migration code, since it only accepts a single dependency
50- * fence.
51- * The single fence returned from these utilities, in the case of
52- * dependencies from multiple fence contexts, a struct dma_fence_array,
53- * since the i915 request code can break that up and await the individual
54- * fences.
45+ * DOC: Set of utilities to dynamically collect dependencies into a
46+ * structure which is fed into the GT migration code.
5547 *
5648 * Once we can do async unbinding, this is also needed to coalesce
57- * the migration fence with the unbind fences.
49+ * the migration fence with the unbind fences if these are coalesced
50+ * post-migration.
5851 *
5952 * While collecting the individual dependencies, we store the refcounted
6053 * struct dma_fence pointers in a realloc-managed pointer array, since
@@ -65,32 +58,13 @@ void i915_ttm_migrate_set_failure_modes(bool gpu_migration,
6558 * A struct i915_deps need to be initialized using i915_deps_init().
6659 * If i915_deps_add_dependency() or i915_deps_add_resv() return an
6760 * error code they will internally call i915_deps_fini(), which frees
68- * all internal references and allocations. After a call to
69- * i915_deps_to_fence(), or i915_deps_sync(), the struct should similarly
70- * be viewed as uninitialized.
61+ * all internal references and allocations.
7162 *
7263 * We might want to break this out into a separate file as a utility.
7364 */
7465
7566#define I915_DEPS_MIN_ALLOC_CHUNK 8U
7667
77- /**
78- * struct i915_deps - Collect dependencies into a single dma-fence
79- * @single: Storage for pointer if the collection is a single fence.
80- * @fence: Allocated array of fence pointers if more than a single fence;
81- * otherwise points to the address of @single.
82- * @num_deps: Current number of dependency fences.
83- * @fences_size: Size of the @fences array in number of pointers.
84- * @gfp: Allocation mode.
85- */
86- struct i915_deps {
87- struct dma_fence * single ;
88- struct dma_fence * * fences ;
89- unsigned int num_deps ;
90- unsigned int fences_size ;
91- gfp_t gfp ;
92- };
93-
9468static void i915_deps_reset_fences (struct i915_deps * deps )
9569{
9670 if (deps -> fences != & deps -> single )
@@ -163,7 +137,7 @@ static int i915_deps_grow(struct i915_deps *deps, struct dma_fence *fence,
163137 return ret ;
164138}
165139
166- static int i915_deps_sync (struct i915_deps * deps ,
140+ static int i915_deps_sync (const struct i915_deps * deps ,
167141 const struct ttm_operation_ctx * ctx )
168142{
169143 struct dma_fence * * fences = deps -> fences ;
@@ -183,7 +157,6 @@ static int i915_deps_sync(struct i915_deps *deps,
183157 break ;
184158 }
185159
186- i915_deps_fini (deps );
187160 return ret ;
188161}
189162
@@ -221,34 +194,6 @@ static int i915_deps_add_dependency(struct i915_deps *deps,
221194 return i915_deps_grow (deps , fence , ctx );
222195}
223196
224- static struct dma_fence * i915_deps_to_fence (struct i915_deps * deps ,
225- const struct ttm_operation_ctx * ctx )
226- {
227- struct dma_fence_array * array ;
228-
229- if (deps -> num_deps == 0 )
230- return NULL ;
231-
232- if (deps -> num_deps == 1 ) {
233- deps -> num_deps = 0 ;
234- return deps -> fences [0 ];
235- }
236-
237- /*
238- * TODO: Alter the allocation mode here to not try too hard to
239- * make things async.
240- */
241- array = dma_fence_array_create (deps -> num_deps , deps -> fences , 0 , 0 ,
242- false);
243- if (!array )
244- return ERR_PTR (i915_deps_sync (deps , ctx ));
245-
246- deps -> fences = NULL ;
247- i915_deps_reset_fences (deps );
248-
249- return & array -> base ;
250- }
251-
252197static int i915_deps_add_resv (struct i915_deps * deps , struct dma_resv * resv ,
253198 bool all , const bool no_excl ,
254199 const struct ttm_operation_ctx * ctx )
@@ -387,7 +332,7 @@ static struct dma_fence *i915_ttm_accel_move(struct ttm_buffer_object *bo,
387332 struct ttm_resource * dst_mem ,
388333 struct ttm_tt * dst_ttm ,
389334 struct sg_table * dst_st ,
390- struct dma_fence * dep )
335+ const struct i915_deps * deps )
391336{
392337 struct drm_i915_private * i915 = container_of (bo -> bdev , typeof (* i915 ),
393338 bdev );
@@ -411,7 +356,7 @@ static struct dma_fence *i915_ttm_accel_move(struct ttm_buffer_object *bo,
411356 return ERR_PTR (- EINVAL );
412357
413358 intel_engine_pm_get (to_gt (i915 )-> migrate .context -> engine );
414- ret = intel_context_migrate_clear (to_gt (i915 )-> migrate .context , dep ,
359+ ret = intel_context_migrate_clear (to_gt (i915 )-> migrate .context , deps ,
415360 dst_st -> sgl , dst_level ,
416361 i915_ttm_gtt_binds_lmem (dst_mem ),
417362 0 , & rq );
@@ -425,7 +370,7 @@ static struct dma_fence *i915_ttm_accel_move(struct ttm_buffer_object *bo,
425370 src_level = i915_ttm_cache_level (i915 , bo -> resource , src_ttm );
426371 intel_engine_pm_get (to_gt (i915 )-> migrate .context -> engine );
427372 ret = intel_context_migrate_copy (to_gt (i915 )-> migrate .context ,
428- dep , src_rsgt -> table .sgl ,
373+ deps , src_rsgt -> table .sgl ,
429374 src_level ,
430375 i915_ttm_gtt_binds_lmem (bo -> resource ),
431376 dst_st -> sgl , dst_level ,
@@ -610,18 +555,19 @@ i915_ttm_memcpy_work_arm(struct i915_ttm_memcpy_work *work,
610555}
611556
612557static struct dma_fence *
613- __i915_ttm_move (struct ttm_buffer_object * bo , bool clear ,
558+ __i915_ttm_move (struct ttm_buffer_object * bo ,
559+ const struct ttm_operation_ctx * ctx , bool clear ,
614560 struct ttm_resource * dst_mem , struct ttm_tt * dst_ttm ,
615561 struct i915_refct_sgt * dst_rsgt , bool allow_accel ,
616- struct dma_fence * move_dep )
562+ const struct i915_deps * move_deps )
617563{
618564 struct i915_ttm_memcpy_work * copy_work = NULL ;
619565 struct i915_ttm_memcpy_arg _arg , * arg = & _arg ;
620566 struct dma_fence * fence = ERR_PTR (- EINVAL );
621567
622568 if (allow_accel ) {
623569 fence = i915_ttm_accel_move (bo , clear , dst_mem , dst_ttm ,
624- & dst_rsgt -> table , move_dep );
570+ & dst_rsgt -> table , move_deps );
625571
626572 /*
627573 * We only need to intercept the error when moving to lmem.
@@ -655,8 +601,8 @@ __i915_ttm_move(struct ttm_buffer_object *bo, bool clear,
655601
656602 if (!IS_ERR (fence ))
657603 goto out ;
658- } else if (move_dep ) {
659- int err = dma_fence_wait ( move_dep , true );
604+ } else if (move_deps ) {
605+ int err = i915_deps_sync ( move_deps , ctx );
660606
661607 if (err )
662608 return ERR_PTR (err );
@@ -680,29 +626,21 @@ __i915_ttm_move(struct ttm_buffer_object *bo, bool clear,
680626 return fence ;
681627}
682628
683- static struct dma_fence * prev_fence (struct ttm_buffer_object * bo ,
684- struct ttm_operation_ctx * ctx )
629+ static int
630+ prev_deps (struct ttm_buffer_object * bo , struct ttm_operation_ctx * ctx ,
631+ struct i915_deps * deps )
685632{
686- struct i915_deps deps ;
687633 int ret ;
688634
689- /*
690- * Instead of trying hard with GFP_KERNEL to allocate memory,
691- * the dependency collection will just sync if it doesn't
692- * succeed.
693- */
694- i915_deps_init (& deps , GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN );
695- ret = i915_deps_add_dependency (& deps , bo -> moving , ctx );
635+ ret = i915_deps_add_dependency (deps , bo -> moving , ctx );
696636 if (!ret )
697637 /*
698638 * TODO: Only await excl fence here, and shared fences before
699639 * signaling the migration fence.
700640 */
701- ret = i915_deps_add_resv (& deps , bo -> base .resv , true, false, ctx );
702- if (ret )
703- return ERR_PTR (ret );
641+ ret = i915_deps_add_resv (deps , bo -> base .resv , true, false, ctx );
704642
705- return i915_deps_to_fence ( & deps , ctx ) ;
643+ return ret ;
706644}
707645
708646/**
@@ -756,16 +694,18 @@ int i915_ttm_move(struct ttm_buffer_object *bo, bool evict,
756694
757695 clear = !i915_ttm_cpu_maps_iomem (bo -> resource ) && (!ttm || !ttm_tt_is_populated (ttm ));
758696 if (!(clear && ttm && !(ttm -> page_flags & TTM_TT_FLAG_ZERO_ALLOC ))) {
759- struct dma_fence * dep = prev_fence ( bo , ctx ) ;
697+ struct i915_deps deps ;
760698
761- if (IS_ERR (dep )) {
699+ i915_deps_init (& deps , GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN );
700+ ret = prev_deps (bo , ctx , & deps );
701+ if (ret ) {
762702 i915_refct_sgt_put (dst_rsgt );
763- return PTR_ERR ( dep ) ;
703+ return ret ;
764704 }
765705
766- migration_fence = __i915_ttm_move (bo , clear , dst_mem , bo -> ttm ,
767- dst_rsgt , true, dep );
768- dma_fence_put ( dep );
706+ migration_fence = __i915_ttm_move (bo , ctx , clear , dst_mem , bo -> ttm ,
707+ dst_rsgt , true, & deps );
708+ i915_deps_fini ( & deps );
769709 }
770710
771711 /* We can possibly get an -ERESTARTSYS here */
@@ -826,7 +766,7 @@ int i915_gem_obj_copy_ttm(struct drm_i915_gem_object *dst,
826766 .interruptible = intr ,
827767 };
828768 struct i915_refct_sgt * dst_rsgt ;
829- struct dma_fence * copy_fence , * dep_fence ;
769+ struct dma_fence * copy_fence ;
830770 struct i915_deps deps ;
831771 int ret , shared_err ;
832772
@@ -847,15 +787,12 @@ int i915_gem_obj_copy_ttm(struct drm_i915_gem_object *dst,
847787 if (ret )
848788 return ret ;
849789
850- dep_fence = i915_deps_to_fence (& deps , & ctx );
851- if (IS_ERR (dep_fence ))
852- return PTR_ERR (dep_fence );
853-
854790 dst_rsgt = i915_ttm_resource_get_st (dst , dst_bo -> resource );
855- copy_fence = __i915_ttm_move (src_bo , false, dst_bo -> resource ,
791+ copy_fence = __i915_ttm_move (src_bo , & ctx , false, dst_bo -> resource ,
856792 dst_bo -> ttm , dst_rsgt , allow_accel ,
857- dep_fence );
793+ & deps );
858794
795+ i915_deps_fini (& deps );
859796 i915_refct_sgt_put (dst_rsgt );
860797 if (IS_ERR_OR_NULL (copy_fence ))
861798 return PTR_ERR_OR_ZERO (copy_fence );
0 commit comments