summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/ttm/ttm_bo_util.c
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2016-06-15 14:44:03 +0300
committerAlex Deucher <alexander.deucher@amd.com>2016-07-07 21:54:41 +0300
commit3ddf4ad9179779693a7656e67872fc37cc49e92b (patch)
tree806b34a24459764c6625a704ea3a73b70f72e6a3 /drivers/gpu/drm/ttm/ttm_bo_util.c
parentf849c6d6527a4108b1d7813e1a0eac9f1568cc4b (diff)
downloadlinux-3ddf4ad9179779693a7656e67872fc37cc49e92b.tar.xz
drm/ttm: add the infrastructure for pipelined evictions
Free up the memory immediately, remember the last eviction for each domain and make new allocations depend on the last eviction to be completed. Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/ttm/ttm_bo_util.c')
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_util.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index 9ea8d02f4ea5..0c389a54cac1 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -696,3 +696,95 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
return 0;
}
EXPORT_SYMBOL(ttm_bo_move_accel_cleanup);
+
+int ttm_bo_pipeline_move(struct ttm_buffer_object *bo,
+ struct fence *fence, bool evict,
+ struct ttm_mem_reg *new_mem)
+{
+ struct ttm_bo_device *bdev = bo->bdev;
+ struct ttm_mem_reg *old_mem = &bo->mem;
+
+ struct ttm_mem_type_manager *from = &bdev->man[old_mem->mem_type];
+ struct ttm_mem_type_manager *to = &bdev->man[new_mem->mem_type];
+
+ int ret;
+
+ reservation_object_add_excl_fence(bo->resv, fence);
+
+ if (!evict) {
+ struct ttm_buffer_object *ghost_obj;
+
+ /**
+ * This should help pipeline ordinary buffer moves.
+ *
+ * Hang old buffer memory on a new buffer object,
+ * and leave it to be released when the GPU
+ * operation has completed.
+ */
+
+ fence_put(bo->moving);
+ bo->moving = fence_get(fence);
+
+ ret = ttm_buffer_object_transfer(bo, &ghost_obj);
+ if (ret)
+ return ret;
+
+ reservation_object_add_excl_fence(ghost_obj->resv, fence);
+
+ /**
+ * If we're not moving to fixed memory, the TTM object
+ * needs to stay alive. Otherwhise hang it on the ghost
+ * bo to be unbound and destroyed.
+ */
+
+ if (!(to->flags & TTM_MEMTYPE_FLAG_FIXED))
+ ghost_obj->ttm = NULL;
+ else
+ bo->ttm = NULL;
+
+ ttm_bo_unreserve(ghost_obj);
+ ttm_bo_unref(&ghost_obj);
+
+ } else if (from->flags & TTM_MEMTYPE_FLAG_FIXED) {
+
+ /**
+ * BO doesn't have a TTM we need to bind/unbind. Just remember
+ * this eviction and free up the allocation
+ */
+
+ spin_lock(&from->move_lock);
+ if (!from->move || fence_is_later(from->move, fence)) {
+ fence_put(from->move);
+ from->move = fence_get(fence);
+ }
+ spin_unlock(&from->move_lock);
+
+ ttm_bo_free_old_node(bo);
+
+ fence_put(bo->moving);
+ bo->moving = fence_get(fence);
+
+ } else {
+ /**
+ * Last resort, wait for the move to be completed.
+ *
+ * Should never happen in pratice.
+ */
+
+ ret = ttm_bo_wait(bo, false, false);
+ if (ret)
+ return ret;
+
+ if (to->flags & TTM_MEMTYPE_FLAG_FIXED) {
+ ttm_tt_destroy(bo->ttm);
+ bo->ttm = NULL;
+ }
+ ttm_bo_free_old_node(bo);
+ }
+
+ *old_mem = *new_mem;
+ new_mem->mm_node = NULL;
+
+ return 0;
+}
+EXPORT_SYMBOL(ttm_bo_pipeline_move);