1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright © 2021 Intel Corporation
4 */
5
6 #include <drm/ttm/ttm_tt.h>
7
8 #include "i915_deps.h"
9 #include "i915_drv.h"
10 #include "intel_memory_region.h"
11 #include "intel_region_ttm.h"
12
13 #include "gem/i915_gem_object.h"
14 #include "gem/i915_gem_region.h"
15 #include "gem/i915_gem_ttm.h"
16 #include "gem/i915_gem_ttm_move.h"
17
18 #include "gt/intel_engine_pm.h"
19 #include "gt/intel_gt.h"
20 #include "gt/intel_migrate.h"
21
22 /**
23 * DOC: Selftest failure modes for failsafe migration:
24 *
25 * For fail_gpu_migration, the gpu blit scheduled is always a clear blit
26 * rather than a copy blit, and then we force the failure paths as if
27 * the blit fence returned an error.
28 *
29 * For fail_work_allocation we fail the kmalloc of the async worker, we
30 * sync the gpu blit. If it then fails, or fail_gpu_migration is set to
31 * true, then a memcpy operation is performed sync.
32 */
33 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
34 static bool fail_gpu_migration;
35 static bool fail_work_allocation;
36 static bool ban_memcpy;
37
i915_ttm_migrate_set_failure_modes(bool gpu_migration,bool work_allocation)38 void i915_ttm_migrate_set_failure_modes(bool gpu_migration,
39 bool work_allocation)
40 {
41 fail_gpu_migration = gpu_migration;
42 fail_work_allocation = work_allocation;
43 }
44
i915_ttm_migrate_set_ban_memcpy(bool ban)45 void i915_ttm_migrate_set_ban_memcpy(bool ban)
46 {
47 ban_memcpy = ban;
48 }
49 #endif
50
51 static enum i915_cache_level
i915_ttm_cache_level(struct drm_i915_private * i915,struct ttm_resource * res,struct ttm_tt * ttm)52 i915_ttm_cache_level(struct drm_i915_private *i915, struct ttm_resource *res,
53 struct ttm_tt *ttm)
54 {
55 return ((HAS_LLC(i915) || HAS_SNOOP(i915)) &&
56 !i915_ttm_gtt_binds_lmem(res) &&
57 ttm->caching == ttm_cached) ? I915_CACHE_LLC :
58 I915_CACHE_NONE;
59 }
60
61 static struct intel_memory_region *
i915_ttm_region(struct ttm_device * bdev,int ttm_mem_type)62 i915_ttm_region(struct ttm_device *bdev, int ttm_mem_type)
63 {
64 struct drm_i915_private *i915 = container_of(bdev, typeof(*i915), bdev);
65
66 /* There's some room for optimization here... */
67 GEM_BUG_ON(ttm_mem_type != I915_PL_SYSTEM &&
68 ttm_mem_type < I915_PL_LMEM0);
69 if (ttm_mem_type == I915_PL_SYSTEM)
70 return intel_memory_region_lookup(i915, INTEL_MEMORY_SYSTEM,
71 0);
72
73 return intel_memory_region_lookup(i915, INTEL_MEMORY_LOCAL,
74 ttm_mem_type - I915_PL_LMEM0);
75 }
76
77 /**
78 * i915_ttm_adjust_domains_after_move - Adjust the GEM domains after a
79 * TTM move
80 * @obj: The gem object
81 */
i915_ttm_adjust_domains_after_move(struct drm_i915_gem_object * obj)82 void i915_ttm_adjust_domains_after_move(struct drm_i915_gem_object *obj)
83 {
84 struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
85
86 if (i915_ttm_cpu_maps_iomem(bo->resource) || bo->ttm->caching != ttm_cached) {
87 obj->write_domain = I915_GEM_DOMAIN_WC;
88 obj->read_domains = I915_GEM_DOMAIN_WC;
89 } else {
90 obj->write_domain = I915_GEM_DOMAIN_CPU;
91 obj->read_domains = I915_GEM_DOMAIN_CPU;
92 }
93 }
94
95 /**
96 * i915_ttm_adjust_gem_after_move - Adjust the GEM state after a TTM move
97 * @obj: The gem object
98 *
99 * Adjusts the GEM object's region, mem_flags and cache coherency after a
100 * TTM move.
101 */
i915_ttm_adjust_gem_after_move(struct drm_i915_gem_object * obj)102 void i915_ttm_adjust_gem_after_move(struct drm_i915_gem_object *obj)
103 {
104 struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
105 unsigned int cache_level;
106 unsigned int mem_flags;
107 unsigned int i;
108 int mem_type;
109
110 /*
111 * We might have been purged (or swapped out) if the resource is NULL,
112 * in which case the SYSTEM placement is the closest match to describe
113 * the current domain. If the object is ever used in this state then we
114 * will require moving it again.
115 */
116 if (!bo->resource) {
117 mem_flags = I915_BO_FLAG_STRUCT_PAGE;
118 mem_type = I915_PL_SYSTEM;
119 cache_level = I915_CACHE_NONE;
120 } else {
121 mem_flags = i915_ttm_cpu_maps_iomem(bo->resource) ? I915_BO_FLAG_IOMEM :
122 I915_BO_FLAG_STRUCT_PAGE;
123 mem_type = bo->resource->mem_type;
124 cache_level = i915_ttm_cache_level(to_i915(bo->base.dev), bo->resource,
125 bo->ttm);
126 }
127
128 /*
129 * If object was moved to an allowable region, update the object
130 * region to consider it migrated. Note that if it's currently not
131 * in an allowable region, it's evicted and we don't update the
132 * object region.
133 */
134 if (intel_region_to_ttm_type(obj->mm.region) != mem_type) {
135 for (i = 0; i < obj->mm.n_placements; ++i) {
136 struct intel_memory_region *mr = obj->mm.placements[i];
137
138 if (intel_region_to_ttm_type(mr) == mem_type &&
139 mr != obj->mm.region) {
140 i915_gem_object_release_memory_region(obj);
141 i915_gem_object_init_memory_region(obj, mr);
142 break;
143 }
144 }
145 }
146
147 obj->mem_flags &= ~(I915_BO_FLAG_STRUCT_PAGE | I915_BO_FLAG_IOMEM);
148 obj->mem_flags |= mem_flags;
149
150 i915_gem_object_set_cache_coherency(obj, cache_level);
151 }
152
153 /**
154 * i915_ttm_move_notify - Prepare an object for move
155 * @bo: The ttm buffer object.
156 *
157 * This function prepares an object for move by removing all GPU bindings,
158 * removing all CPU mapings and finally releasing the pages sg-table.
159 *
160 * Return: 0 if successful, negative error code on error.
161 */
i915_ttm_move_notify(struct ttm_buffer_object * bo)162 int i915_ttm_move_notify(struct ttm_buffer_object *bo)
163 {
164 struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
165 int ret;
166
167 /*
168 * Note: The async unbinding here will actually transform the
169 * blocking wait for unbind into a wait before finally submitting
170 * evict / migration blit and thus stall the migration timeline
171 * which may not be good for overall throughput. We should make
172 * sure we await the unbind fences *after* the migration blit
173 * instead of *before* as we currently do.
174 */
175 ret = i915_gem_object_unbind(obj, I915_GEM_OBJECT_UNBIND_ACTIVE |
176 I915_GEM_OBJECT_UNBIND_ASYNC);
177 if (ret)
178 return ret;
179
180 ret = __i915_gem_object_put_pages(obj);
181 if (ret)
182 return ret;
183
184 return 0;
185 }
186
i915_ttm_accel_move(struct ttm_buffer_object * bo,bool clear,struct ttm_resource * dst_mem,struct ttm_tt * dst_ttm,struct sg_table * dst_st,const struct i915_deps * deps)187 static struct dma_fence *i915_ttm_accel_move(struct ttm_buffer_object *bo,
188 bool clear,
189 struct ttm_resource *dst_mem,
190 struct ttm_tt *dst_ttm,
191 struct sg_table *dst_st,
192 const struct i915_deps *deps)
193 {
194 struct drm_i915_private *i915 = container_of(bo->bdev, typeof(*i915),
195 bdev);
196 struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
197 struct i915_request *rq;
198 struct ttm_tt *src_ttm = bo->ttm;
199 enum i915_cache_level src_level, dst_level;
200 int ret;
201
202 if (!to_gt(i915)->migrate.context || intel_gt_is_wedged(to_gt(i915)))
203 return ERR_PTR(-EINVAL);
204
205 /* With fail_gpu_migration, we always perform a GPU clear. */
206 if (I915_SELFTEST_ONLY(fail_gpu_migration))
207 clear = true;
208
209 dst_level = i915_ttm_cache_level(i915, dst_mem, dst_ttm);
210 if (clear) {
211 if (bo->type == ttm_bo_type_kernel &&
212 !I915_SELFTEST_ONLY(fail_gpu_migration))
213 return ERR_PTR(-EINVAL);
214
215 intel_engine_pm_get(to_gt(i915)->migrate.context->engine);
216 ret = intel_context_migrate_clear(to_gt(i915)->migrate.context, deps,
217 dst_st->sgl,
218 i915_gem_get_pat_index(i915, dst_level),
219 i915_ttm_gtt_binds_lmem(dst_mem),
220 0, &rq);
221 } else {
222 struct i915_refct_sgt *src_rsgt =
223 i915_ttm_resource_get_st(obj, bo->resource);
224
225 if (IS_ERR(src_rsgt))
226 return ERR_CAST(src_rsgt);
227
228 src_level = i915_ttm_cache_level(i915, bo->resource, src_ttm);
229 intel_engine_pm_get(to_gt(i915)->migrate.context->engine);
230 ret = intel_context_migrate_copy(to_gt(i915)->migrate.context,
231 deps, src_rsgt->table.sgl,
232 i915_gem_get_pat_index(i915, src_level),
233 i915_ttm_gtt_binds_lmem(bo->resource),
234 dst_st->sgl,
235 i915_gem_get_pat_index(i915, dst_level),
236 i915_ttm_gtt_binds_lmem(dst_mem),
237 &rq);
238
239 i915_refct_sgt_put(src_rsgt);
240 }
241
242 intel_engine_pm_put(to_gt(i915)->migrate.context->engine);
243
244 if (ret && rq) {
245 i915_request_wait(rq, 0, MAX_SCHEDULE_TIMEOUT);
246 i915_request_put(rq);
247 }
248
249 return ret ? ERR_PTR(ret) : &rq->fence;
250 }
251
252 /**
253 * struct i915_ttm_memcpy_arg - argument for the bo memcpy functionality.
254 * @_dst_iter: Storage space for the destination kmap iterator.
255 * @_src_iter: Storage space for the source kmap iterator.
256 * @dst_iter: Pointer to the destination kmap iterator.
257 * @src_iter: Pointer to the source kmap iterator.
258 * @num_pages: Number of pages
259 * @clear: Whether to clear instead of copy.
260 * @src_rsgt: Refcounted scatter-gather list of source memory.
261 * @dst_rsgt: Refcounted scatter-gather list of destination memory.
262 */
263 struct i915_ttm_memcpy_arg {
264 union {
265 struct ttm_kmap_iter_tt tt;
266 struct ttm_kmap_iter_iomap io;
267 } _dst_iter,
268 _src_iter;
269 struct ttm_kmap_iter *dst_iter;
270 struct ttm_kmap_iter *src_iter;
271 unsigned long num_pages;
272 bool clear;
273 struct i915_refct_sgt *src_rsgt;
274 struct i915_refct_sgt *dst_rsgt;
275 bus_space_tag_t memt;
276 };
277
278 /**
279 * struct i915_ttm_memcpy_work - Async memcpy worker under a dma-fence.
280 * @fence: The dma-fence.
281 * @work: The work struct use for the memcpy work.
282 * @lock: The fence lock. Not used to protect anything else ATM.
283 * @irq_work: Low latency worker to signal the fence since it can't be done
284 * from the callback for lockdep reasons.
285 * @cb: Callback for the accelerated migration fence.
286 * @arg: The argument for the memcpy functionality.
287 * @i915: The i915 pointer.
288 * @obj: The GEM object.
289 * @memcpy_allowed: Instead of processing the @arg, and falling back to memcpy
290 * or memset, we wedge the device and set the @obj unknown_state, to prevent
291 * further access to the object with the CPU or GPU. On some devices we might
292 * only be permitted to use the blitter engine for such operations.
293 */
294 struct i915_ttm_memcpy_work {
295 struct dma_fence fence;
296 struct work_struct work;
297 spinlock_t lock;
298 struct irq_work irq_work;
299 struct dma_fence_cb cb;
300 struct i915_ttm_memcpy_arg arg;
301 struct drm_i915_private *i915;
302 struct drm_i915_gem_object *obj;
303 bool memcpy_allowed;
304 };
305
i915_ttm_move_memcpy(struct i915_ttm_memcpy_arg * arg)306 static void i915_ttm_move_memcpy(struct i915_ttm_memcpy_arg *arg)
307 {
308 ttm_move_memcpy(arg->clear, arg->num_pages,
309 arg->dst_iter, arg->src_iter, arg->memt);
310 }
311
i915_ttm_memcpy_init(struct i915_ttm_memcpy_arg * arg,struct ttm_buffer_object * bo,bool clear,struct ttm_resource * dst_mem,struct ttm_tt * dst_ttm,struct i915_refct_sgt * dst_rsgt)312 static void i915_ttm_memcpy_init(struct i915_ttm_memcpy_arg *arg,
313 struct ttm_buffer_object *bo, bool clear,
314 struct ttm_resource *dst_mem,
315 struct ttm_tt *dst_ttm,
316 struct i915_refct_sgt *dst_rsgt)
317 {
318 struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
319 struct intel_memory_region *dst_reg, *src_reg;
320
321 dst_reg = i915_ttm_region(bo->bdev, dst_mem->mem_type);
322 src_reg = i915_ttm_region(bo->bdev, bo->resource->mem_type);
323 GEM_BUG_ON(!dst_reg || !src_reg);
324
325 arg->dst_iter = !i915_ttm_cpu_maps_iomem(dst_mem) ?
326 ttm_kmap_iter_tt_init(&arg->_dst_iter.tt, dst_ttm) :
327 ttm_kmap_iter_iomap_init(&arg->_dst_iter.io, &dst_reg->iomap,
328 &dst_rsgt->table, dst_reg->region.start);
329
330 arg->src_iter = !i915_ttm_cpu_maps_iomem(bo->resource) ?
331 ttm_kmap_iter_tt_init(&arg->_src_iter.tt, bo->ttm) :
332 ttm_kmap_iter_iomap_init(&arg->_src_iter.io, &src_reg->iomap,
333 &obj->ttm.cached_io_rsgt->table,
334 src_reg->region.start);
335 arg->clear = clear;
336 arg->num_pages = bo->base.size >> PAGE_SHIFT;
337
338 arg->dst_rsgt = i915_refct_sgt_get(dst_rsgt);
339 arg->src_rsgt = clear ? NULL :
340 i915_ttm_resource_get_st(obj, bo->resource);
341
342 arg->memt = bo->bdev->memt;
343 }
344
i915_ttm_memcpy_release(struct i915_ttm_memcpy_arg * arg)345 static void i915_ttm_memcpy_release(struct i915_ttm_memcpy_arg *arg)
346 {
347 i915_refct_sgt_put(arg->src_rsgt);
348 i915_refct_sgt_put(arg->dst_rsgt);
349 }
350
__memcpy_work(struct work_struct * work)351 static void __memcpy_work(struct work_struct *work)
352 {
353 struct i915_ttm_memcpy_work *copy_work =
354 container_of(work, typeof(*copy_work), work);
355 struct i915_ttm_memcpy_arg *arg = ©_work->arg;
356 bool cookie;
357
358 /*
359 * FIXME: We need to take a closer look here. We should be able to plonk
360 * this into the fence critical section.
361 */
362 if (!copy_work->memcpy_allowed) {
363 struct intel_gt *gt;
364 unsigned int id;
365
366 for_each_gt(gt, copy_work->i915, id)
367 intel_gt_set_wedged(gt);
368 }
369
370 cookie = dma_fence_begin_signalling();
371
372 if (copy_work->memcpy_allowed) {
373 i915_ttm_move_memcpy(arg);
374 } else {
375 /*
376 * Prevent further use of the object. Any future GTT binding or
377 * CPU access is not allowed once we signal the fence. Outside
378 * of the fence critical section, we then also then wedge the gpu
379 * to indicate the device is not functional.
380 *
381 * The below dma_fence_signal() is our write-memory-barrier.
382 */
383 copy_work->obj->mm.unknown_state = true;
384 }
385
386 dma_fence_end_signalling(cookie);
387
388 dma_fence_signal(©_work->fence);
389
390 i915_ttm_memcpy_release(arg);
391 i915_gem_object_put(copy_work->obj);
392 dma_fence_put(©_work->fence);
393 }
394
__memcpy_irq_work(struct irq_work * irq_work)395 static void __memcpy_irq_work(struct irq_work *irq_work)
396 {
397 struct i915_ttm_memcpy_work *copy_work =
398 container_of(irq_work, typeof(*copy_work), irq_work);
399 struct i915_ttm_memcpy_arg *arg = ©_work->arg;
400
401 dma_fence_signal(©_work->fence);
402 i915_ttm_memcpy_release(arg);
403 i915_gem_object_put(copy_work->obj);
404 dma_fence_put(©_work->fence);
405 }
406
__memcpy_cb(struct dma_fence * fence,struct dma_fence_cb * cb)407 static void __memcpy_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
408 {
409 struct i915_ttm_memcpy_work *copy_work =
410 container_of(cb, typeof(*copy_work), cb);
411
412 if (unlikely(fence->error || I915_SELFTEST_ONLY(fail_gpu_migration))) {
413 INIT_WORK(©_work->work, __memcpy_work);
414 queue_work(system_unbound_wq, ©_work->work);
415 } else {
416 init_irq_work(©_work->irq_work, __memcpy_irq_work);
417 irq_work_queue(©_work->irq_work);
418 }
419 }
420
get_driver_name(struct dma_fence * fence)421 static const char *get_driver_name(struct dma_fence *fence)
422 {
423 return "i915_ttm_memcpy_work";
424 }
425
get_timeline_name(struct dma_fence * fence)426 static const char *get_timeline_name(struct dma_fence *fence)
427 {
428 return "unbound";
429 }
430
431 static const struct dma_fence_ops dma_fence_memcpy_ops = {
432 .get_driver_name = get_driver_name,
433 .get_timeline_name = get_timeline_name,
434 };
435
436 static struct dma_fence *
i915_ttm_memcpy_work_arm(struct i915_ttm_memcpy_work * work,struct dma_fence * dep)437 i915_ttm_memcpy_work_arm(struct i915_ttm_memcpy_work *work,
438 struct dma_fence *dep)
439 {
440 int ret;
441
442 mtx_init(&work->lock, IPL_TTY);
443 dma_fence_init(&work->fence, &dma_fence_memcpy_ops, &work->lock, 0, 0);
444 dma_fence_get(&work->fence);
445 ret = dma_fence_add_callback(dep, &work->cb, __memcpy_cb);
446 if (ret) {
447 if (ret != -ENOENT)
448 dma_fence_wait(dep, false);
449
450 return ERR_PTR(I915_SELFTEST_ONLY(fail_gpu_migration) ? -EINVAL :
451 dep->error);
452 }
453
454 return &work->fence;
455 }
456
i915_ttm_memcpy_allowed(struct ttm_buffer_object * bo,struct ttm_resource * dst_mem)457 static bool i915_ttm_memcpy_allowed(struct ttm_buffer_object *bo,
458 struct ttm_resource *dst_mem)
459 {
460 if (i915_gem_object_needs_ccs_pages(i915_ttm_to_gem(bo)))
461 return false;
462
463 if (!(i915_ttm_resource_mappable(bo->resource) &&
464 i915_ttm_resource_mappable(dst_mem)))
465 return false;
466
467 return I915_SELFTEST_ONLY(ban_memcpy) ? false : true;
468 }
469
470 static struct dma_fence *
__i915_ttm_move(struct ttm_buffer_object * bo,const struct ttm_operation_ctx * ctx,bool clear,struct ttm_resource * dst_mem,struct ttm_tt * dst_ttm,struct i915_refct_sgt * dst_rsgt,bool allow_accel,const struct i915_deps * move_deps)471 __i915_ttm_move(struct ttm_buffer_object *bo,
472 const struct ttm_operation_ctx *ctx, bool clear,
473 struct ttm_resource *dst_mem, struct ttm_tt *dst_ttm,
474 struct i915_refct_sgt *dst_rsgt, bool allow_accel,
475 const struct i915_deps *move_deps)
476 {
477 const bool memcpy_allowed = i915_ttm_memcpy_allowed(bo, dst_mem);
478 struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
479 struct drm_i915_private *i915 = to_i915(bo->base.dev);
480 struct i915_ttm_memcpy_work *copy_work = NULL;
481 struct i915_ttm_memcpy_arg _arg, *arg = &_arg;
482 struct dma_fence *fence = ERR_PTR(-EINVAL);
483
484 if (allow_accel) {
485 fence = i915_ttm_accel_move(bo, clear, dst_mem, dst_ttm,
486 &dst_rsgt->table, move_deps);
487
488 /*
489 * We only need to intercept the error when moving to lmem.
490 * When moving to system, TTM or shmem will provide us with
491 * cleared pages.
492 */
493 if (!IS_ERR(fence) && !i915_ttm_gtt_binds_lmem(dst_mem) &&
494 !I915_SELFTEST_ONLY(fail_gpu_migration ||
495 fail_work_allocation))
496 goto out;
497 }
498
499 /* If we've scheduled gpu migration. Try to arm error intercept. */
500 if (!IS_ERR(fence)) {
501 struct dma_fence *dep = fence;
502
503 if (!I915_SELFTEST_ONLY(fail_work_allocation))
504 copy_work = kzalloc(sizeof(*copy_work), GFP_KERNEL);
505
506 if (copy_work) {
507 copy_work->i915 = i915;
508 copy_work->memcpy_allowed = memcpy_allowed;
509 copy_work->obj = i915_gem_object_get(obj);
510 arg = ©_work->arg;
511 if (memcpy_allowed)
512 i915_ttm_memcpy_init(arg, bo, clear, dst_mem,
513 dst_ttm, dst_rsgt);
514
515 fence = i915_ttm_memcpy_work_arm(copy_work, dep);
516 } else {
517 dma_fence_wait(dep, false);
518 fence = ERR_PTR(I915_SELFTEST_ONLY(fail_gpu_migration) ?
519 -EINVAL : fence->error);
520 }
521 dma_fence_put(dep);
522
523 if (!IS_ERR(fence))
524 goto out;
525 } else {
526 int err = PTR_ERR(fence);
527
528 if (err == -EINTR || err == -ERESTARTSYS || err == -EAGAIN)
529 return fence;
530
531 if (move_deps) {
532 err = i915_deps_sync(move_deps, ctx);
533 if (err)
534 return ERR_PTR(err);
535 }
536 }
537
538 /* Error intercept failed or no accelerated migration to start with */
539
540 if (memcpy_allowed) {
541 if (!copy_work)
542 i915_ttm_memcpy_init(arg, bo, clear, dst_mem, dst_ttm,
543 dst_rsgt);
544 i915_ttm_move_memcpy(arg);
545 i915_ttm_memcpy_release(arg);
546 }
547 if (copy_work)
548 i915_gem_object_put(copy_work->obj);
549 kfree(copy_work);
550
551 return memcpy_allowed ? NULL : ERR_PTR(-EIO);
552 out:
553 if (!fence && copy_work) {
554 i915_ttm_memcpy_release(arg);
555 i915_gem_object_put(copy_work->obj);
556 kfree(copy_work);
557 }
558
559 return fence;
560 }
561
562 /**
563 * i915_ttm_move - The TTM move callback used by i915.
564 * @bo: The buffer object.
565 * @evict: Whether this is an eviction.
566 * @ctx: Pointer to a struct ttm_operation_ctx indicating how the waits should be
567 * performed if waiting
568 * @dst_mem: The destination ttm resource.
569 * @hop: If we need multihop, what temporary memory type to move to.
570 *
571 * Return: 0 if successful, negative error code otherwise.
572 */
i915_ttm_move(struct ttm_buffer_object * bo,bool evict,struct ttm_operation_ctx * ctx,struct ttm_resource * dst_mem,struct ttm_place * hop)573 int i915_ttm_move(struct ttm_buffer_object *bo, bool evict,
574 struct ttm_operation_ctx *ctx,
575 struct ttm_resource *dst_mem,
576 struct ttm_place *hop)
577 {
578 struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
579 struct ttm_resource_manager *dst_man =
580 ttm_manager_type(bo->bdev, dst_mem->mem_type);
581 struct dma_fence *migration_fence = NULL;
582 struct ttm_tt *ttm = bo->ttm;
583 struct i915_refct_sgt *dst_rsgt;
584 bool clear, prealloc_bo;
585 int ret;
586
587 if (GEM_WARN_ON(i915_ttm_is_ghost_object(bo))) {
588 ttm_bo_move_null(bo, dst_mem);
589 return 0;
590 }
591
592 if (!bo->resource) {
593 if (dst_mem->mem_type != TTM_PL_SYSTEM) {
594 hop->mem_type = TTM_PL_SYSTEM;
595 hop->flags = TTM_PL_FLAG_TEMPORARY;
596 return -EMULTIHOP;
597 }
598
599 /*
600 * This is only reached when first creating the object, or if
601 * the object was purged or swapped out (pipeline-gutting). For
602 * the former we can safely skip all of the below since we are
603 * only using a dummy SYSTEM placement here. And with the latter
604 * we will always re-enter here with bo->resource set correctly
605 * (as per the above), since this is part of a multi-hop
606 * sequence, where at the end we can do the move for real.
607 *
608 * The special case here is when the dst_mem is TTM_PL_SYSTEM,
609 * which doens't require any kind of move, so it should be safe
610 * to skip all the below and call ttm_bo_move_null() here, where
611 * the caller in __i915_ttm_get_pages() will take care of the
612 * rest, since we should have a valid ttm_tt.
613 */
614 ttm_bo_move_null(bo, dst_mem);
615 return 0;
616 }
617
618 ret = i915_ttm_move_notify(bo);
619 if (ret)
620 return ret;
621
622 if (obj->mm.madv != I915_MADV_WILLNEED) {
623 i915_ttm_purge(obj);
624 ttm_resource_free(bo, &dst_mem);
625 return 0;
626 }
627
628 /* Populate ttm with pages if needed. Typically system memory. */
629 if (ttm && (dst_man->use_tt || (ttm->page_flags & TTM_TT_FLAG_SWAPPED))) {
630 ret = ttm_tt_populate(bo->bdev, ttm, ctx);
631 if (ret)
632 return ret;
633 }
634
635 dst_rsgt = i915_ttm_resource_get_st(obj, dst_mem);
636 if (IS_ERR(dst_rsgt))
637 return PTR_ERR(dst_rsgt);
638
639 clear = !i915_ttm_cpu_maps_iomem(bo->resource) && (!ttm || !ttm_tt_is_populated(ttm));
640 prealloc_bo = obj->flags & I915_BO_PREALLOC;
641 if (!(clear && ttm && !((ttm->page_flags & TTM_TT_FLAG_ZERO_ALLOC) && !prealloc_bo))) {
642 struct i915_deps deps;
643
644 i915_deps_init(&deps, GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);
645 ret = i915_deps_add_resv(&deps, bo->base.resv, ctx);
646 if (ret) {
647 i915_refct_sgt_put(dst_rsgt);
648 return ret;
649 }
650
651 migration_fence = __i915_ttm_move(bo, ctx, clear, dst_mem, ttm,
652 dst_rsgt, true, &deps);
653 i915_deps_fini(&deps);
654 }
655
656 /* We can possibly get an -ERESTARTSYS here */
657 if (IS_ERR(migration_fence)) {
658 i915_refct_sgt_put(dst_rsgt);
659 return PTR_ERR(migration_fence);
660 }
661
662 if (migration_fence) {
663 if (I915_SELFTEST_ONLY(evict && fail_gpu_migration))
664 ret = -EIO; /* never feed non-migrate fences into ttm */
665 else
666 ret = ttm_bo_move_accel_cleanup(bo, migration_fence, evict,
667 true, dst_mem);
668 if (ret) {
669 dma_fence_wait(migration_fence, false);
670 ttm_bo_move_sync_cleanup(bo, dst_mem);
671 }
672 dma_fence_put(migration_fence);
673 } else {
674 ttm_bo_move_sync_cleanup(bo, dst_mem);
675 }
676
677 i915_ttm_adjust_domains_after_move(obj);
678 i915_ttm_free_cached_io_rsgt(obj);
679
680 if (i915_ttm_gtt_binds_lmem(dst_mem) || i915_ttm_cpu_maps_iomem(dst_mem)) {
681 obj->ttm.cached_io_rsgt = dst_rsgt;
682 obj->ttm.get_io_page.sg_pos = dst_rsgt->table.sgl;
683 obj->ttm.get_io_page.sg_idx = 0;
684 } else {
685 i915_refct_sgt_put(dst_rsgt);
686 }
687
688 i915_ttm_adjust_lru(obj);
689 i915_ttm_adjust_gem_after_move(obj);
690 return 0;
691 }
692
693 /**
694 * i915_gem_obj_copy_ttm - Copy the contents of one ttm-based gem object to
695 * another
696 * @dst: The destination object
697 * @src: The source object
698 * @allow_accel: Allow using the blitter. Otherwise TTM memcpy is used.
699 * @intr: Whether to perform waits interruptible:
700 *
701 * Note: The caller is responsible for assuring that the underlying
702 * TTM objects are populated if needed and locked.
703 *
704 * Return: Zero on success. Negative error code on error. If @intr == true,
705 * then it may return -ERESTARTSYS or -EINTR.
706 */
i915_gem_obj_copy_ttm(struct drm_i915_gem_object * dst,struct drm_i915_gem_object * src,bool allow_accel,bool intr)707 int i915_gem_obj_copy_ttm(struct drm_i915_gem_object *dst,
708 struct drm_i915_gem_object *src,
709 bool allow_accel, bool intr)
710 {
711 struct ttm_buffer_object *dst_bo = i915_gem_to_ttm(dst);
712 struct ttm_buffer_object *src_bo = i915_gem_to_ttm(src);
713 struct ttm_operation_ctx ctx = {
714 .interruptible = intr,
715 };
716 struct i915_refct_sgt *dst_rsgt;
717 struct dma_fence *copy_fence;
718 struct i915_deps deps;
719 int ret;
720
721 assert_object_held(dst);
722 assert_object_held(src);
723
724 if (GEM_WARN_ON(!src_bo->resource || !dst_bo->resource))
725 return -EINVAL;
726
727 i915_deps_init(&deps, GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);
728
729 ret = dma_resv_reserve_fences(src_bo->base.resv, 1);
730 if (ret)
731 return ret;
732
733 ret = dma_resv_reserve_fences(dst_bo->base.resv, 1);
734 if (ret)
735 return ret;
736
737 ret = i915_deps_add_resv(&deps, dst_bo->base.resv, &ctx);
738 if (ret)
739 return ret;
740
741 ret = i915_deps_add_resv(&deps, src_bo->base.resv, &ctx);
742 if (ret)
743 return ret;
744
745 dst_rsgt = i915_ttm_resource_get_st(dst, dst_bo->resource);
746 copy_fence = __i915_ttm_move(src_bo, &ctx, false, dst_bo->resource,
747 dst_bo->ttm, dst_rsgt, allow_accel,
748 &deps);
749
750 i915_deps_fini(&deps);
751 i915_refct_sgt_put(dst_rsgt);
752 if (IS_ERR_OR_NULL(copy_fence))
753 return PTR_ERR_OR_ZERO(copy_fence);
754
755 dma_resv_add_fence(dst_bo->base.resv, copy_fence, DMA_RESV_USAGE_WRITE);
756 dma_resv_add_fence(src_bo->base.resv, copy_fence, DMA_RESV_USAGE_READ);
757 dma_fence_put(copy_fence);
758
759 return 0;
760 }
761