[PATCH 3/3] drm/ttm: avoid multihop moves in drivers.

Christian König christian.koenig at amd.com
Wed Oct 21 10:58:13 UTC 2020


Am 21.10.20 um 10:33 schrieb Daniel Vetter:
> On Wed, Oct 21, 2020 at 02:40:31PM +1000, Dave Airlie wrote:
>> From: Dave Airlie <airlied at redhat.com>
>>
>> Currently drivers get called to move a buffer, but if they have to
>> move it temporarily through another space (SYSTEM->VRAM via TT)
>> then they can end up with a lot of ttm->driver->ttm call stacks,
>> if the temprorary space moves requires eviction.
>>
>> Instead of letting the driver do all the placement/space for the
>> temporary, allow it to report back (-EMULTIHOP) a placement (hop)
>> to the move code, which will then do the temporary move, and the
>> correct placement move afterwards.
>>
>> This removes a lot of code from drivers, at the expense of
>> adding some midlayering. I've some further ideas on how to turn
>> it inside out, but I think this is a good solution to the call
>> stack problems.
>>
>> Signed-off-by: Dave Airlie <airlied at redhat.com>
> So at first I freaked out about this a bit on irc, as in "this is horrible
> midlayer madness". But it does look a lot cleaner, it's definitely a step
> in the right direction, and I guess for most drivers it's going to be good
> enough. Maybe there's going to be drivers which want to have even better
> control over where buffers are placed, who's victimized, and what
> intermediate steps to take. But doing that demidlayering can be done when
> there's a need, I think all the building blocks with the in-flight
> untangling are there now.
>
> So I guess I like this now after the initial shock passed :-)

Essentially this is a really big de-midlayering :)

See previously the call chain was like this: 
driver->ttm->driver->ttm->driver->ttm->driver....

For each multi hop we played ping/pong once between driver and ttm :)

Now we at least only have driver->ttm->driver. Which is not ideal 
either, but still a lot better than before.

Christian.

> -Daniel
>
>> ---
>>   drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c    | 139 +++------------------
>>   drivers/gpu/drm/drm_gem_vram_helper.c      |   3 +-
>>   drivers/gpu/drm/nouveau/nouveau_bo.c       | 115 +++--------------
>>   drivers/gpu/drm/qxl/qxl_ttm.c              |   3 +-
>>   drivers/gpu/drm/radeon/radeon_ttm.c        | 122 +++---------------
>>   drivers/gpu/drm/ttm/ttm_bo.c               |  62 +++++++--
>>   drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c |   3 +-
>>   include/drm/ttm/ttm_bo_driver.h            |   5 +-
>>   8 files changed, 108 insertions(+), 344 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
>> index 62f9194b1dd1..0fd4f270d794 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
>> @@ -515,119 +515,6 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
>>   	return r;
>>   }
>>   
>> -/**
>> - * amdgpu_move_vram_ram - Copy VRAM buffer to RAM buffer
>> - *
>> - * Called by amdgpu_bo_move().
>> - */
>> -static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict,
>> -				struct ttm_operation_ctx *ctx,
>> -				struct ttm_resource *new_mem)
>> -{
>> -	struct ttm_resource *old_mem = &bo->mem;
>> -	struct ttm_resource tmp_mem;
>> -	struct ttm_place placements;
>> -	struct ttm_placement placement;
>> -	int r;
>> -
>> -	/* create space/pages for new_mem in GTT space */
>> -	tmp_mem = *new_mem;
>> -	tmp_mem.mm_node = NULL;
>> -	placement.num_placement = 1;
>> -	placement.placement = &placements;
>> -	placement.num_busy_placement = 1;
>> -	placement.busy_placement = &placements;
>> -	placements.fpfn = 0;
>> -	placements.lpfn = 0;
>> -	placements.mem_type = TTM_PL_TT;
>> -	placements.flags = 0;
>> -	r = ttm_bo_mem_space(bo, &placement, &tmp_mem, ctx);
>> -	if (unlikely(r)) {
>> -		pr_err("Failed to find GTT space for blit from VRAM\n");
>> -		return r;
>> -	}
>> -
>> -	r = ttm_tt_populate(bo->bdev, bo->ttm, ctx);
>> -	if (unlikely(r))
>> -		goto out_cleanup;
>> -
>> -	/* Bind the memory to the GTT space */
>> -	r = amdgpu_ttm_backend_bind(bo->bdev, bo->ttm, &tmp_mem);
>> -	if (unlikely(r)) {
>> -		goto out_cleanup;
>> -	}
>> -
>> -	/* blit VRAM to GTT */
>> -	r = amdgpu_move_blit(bo, evict, &tmp_mem, old_mem);
>> -	if (unlikely(r)) {
>> -		goto out_cleanup;
>> -	}
>> -
>> -	r = ttm_bo_wait_ctx(bo, ctx);
>> -	if (unlikely(r))
>> -		goto out_cleanup;
>> -
>> -	amdgpu_ttm_backend_unbind(bo->bdev, bo->ttm);
>> -	ttm_resource_free(bo, &bo->mem);
>> -	ttm_bo_assign_mem(bo, new_mem);
>> -out_cleanup:
>> -	ttm_resource_free(bo, &tmp_mem);
>> -	return r;
>> -}
>> -
>> -/**
>> - * amdgpu_move_ram_vram - Copy buffer from RAM to VRAM
>> - *
>> - * Called by amdgpu_bo_move().
>> - */
>> -static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict,
>> -				struct ttm_operation_ctx *ctx,
>> -				struct ttm_resource *new_mem)
>> -{
>> -	struct ttm_resource *old_mem = &bo->mem;
>> -	struct ttm_resource tmp_mem;
>> -	struct ttm_placement placement;
>> -	struct ttm_place placements;
>> -	int r;
>> -
>> -	/* make space in GTT for old_mem buffer */
>> -	tmp_mem = *new_mem;
>> -	tmp_mem.mm_node = NULL;
>> -	placement.num_placement = 1;
>> -	placement.placement = &placements;
>> -	placement.num_busy_placement = 1;
>> -	placement.busy_placement = &placements;
>> -	placements.fpfn = 0;
>> -	placements.lpfn = 0;
>> -	placements.mem_type = TTM_PL_TT;
>> -	placements.flags = 0;
>> -	r = ttm_bo_mem_space(bo, &placement, &tmp_mem, ctx);
>> -	if (unlikely(r)) {
>> -		pr_err("Failed to find GTT space for blit to VRAM\n");
>> -		return r;
>> -	}
>> -
>> -	/* move/bind old memory to GTT space */
>> -	r = ttm_tt_populate(bo->bdev, bo->ttm, ctx);
>> -	if (unlikely(r))
>> -		return r;
>> -
>> -	r = amdgpu_ttm_backend_bind(bo->bdev, bo->ttm, &tmp_mem);
>> -	if (unlikely(r)) {
>> -		goto out_cleanup;
>> -	}
>> -
>> -	ttm_bo_assign_mem(bo, &tmp_mem);
>> -	/* copy to VRAM */
>> -	r = amdgpu_move_blit(bo, evict, new_mem, old_mem);
>> -	if (unlikely(r)) {
>> -		goto out_cleanup;
>> -	}
>> -out_cleanup:
>> -	ttm_resource_free(bo, &tmp_mem);
>> -	return r;
>> -}
>> -
>>   /**
>>    * amdgpu_mem_visible - Check that memory can be accessed by ttm_bo_move_memcpy
>>    *
>> @@ -659,13 +546,25 @@ static bool amdgpu_mem_visible(struct amdgpu_device *adev,
>>    */
>>   static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
>>   			  struct ttm_operation_ctx *ctx,
>> -			  struct ttm_resource *new_mem)
>> +			  struct ttm_resource *new_mem,
>> +			  struct ttm_place *hop)
>>   {
>>   	struct amdgpu_device *adev;
>>   	struct amdgpu_bo *abo;
>>   	struct ttm_resource *old_mem = &bo->mem;
>>   	int r;
>>   
>> +	if ((old_mem->mem_type == TTM_PL_SYSTEM &&
>> +	     new_mem->mem_type == TTM_PL_VRAM) ||
>> +	    (old_mem->mem_type == TTM_PL_VRAM &&
>> +	     new_mem->mem_type == TTM_PL_SYSTEM)) {
>> +		hop->fpfn = 0;
>> +		hop->lpfn = 0;
>> +		hop->mem_type = TTM_PL_TT;
>> +		hop->flags = 0;
>> +		return -EMULTIHOP;
>> +	}
>> +
>>   	if (new_mem->mem_type == TTM_PL_TT) {
>>   		r = amdgpu_ttm_backend_bind(bo->bdev, bo->ttm, new_mem);
>>   		if (r)
>> @@ -719,16 +618,8 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
>>   		goto memcpy;
>>   	}
>>   
>> -	if (old_mem->mem_type == TTM_PL_VRAM &&
>> -	    new_mem->mem_type == TTM_PL_SYSTEM) {
>> -		r = amdgpu_move_vram_ram(bo, evict, ctx, new_mem);
>> -	} else if (old_mem->mem_type == TTM_PL_SYSTEM &&
>> -		   new_mem->mem_type == TTM_PL_VRAM) {
>> -		r = amdgpu_move_ram_vram(bo, evict, ctx, new_mem);
>> -	} else {
>> -		r = amdgpu_move_blit(bo, evict,
>> -				     new_mem, old_mem);
>> -	}
>> +	r = amdgpu_move_blit(bo, evict,
>> +			     new_mem, old_mem);
>>   
>>   	if (r) {
>>   memcpy:
>> diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c
>> index 9da823eb0edd..c51096cc7fb2 100644
>> --- a/drivers/gpu/drm/drm_gem_vram_helper.c
>> +++ b/drivers/gpu/drm/drm_gem_vram_helper.c
>> @@ -965,7 +965,8 @@ static void bo_driver_delete_mem_notify(struct ttm_buffer_object *bo)
>>   static int bo_driver_move(struct ttm_buffer_object *bo,
>>   			  bool evict,
>>   			  struct ttm_operation_ctx *ctx,
>> -			  struct ttm_resource *new_mem)
>> +			  struct ttm_resource *new_mem,
>> +			  struct ttm_place *hop)
>>   {
>>   	struct drm_gem_vram_object *gbo;
>>   
>> diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
>> index acff82afe260..623577412d19 100644
>> --- a/drivers/gpu/drm/nouveau/nouveau_bo.c
>> +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
>> @@ -862,96 +862,6 @@ nouveau_bo_move_init(struct nouveau_drm *drm)
>>   	NV_INFO(drm, "MM: using %s for buffer copies\n", name);
>>   }
>>   
>> -static int
>> -nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict,
>> -		      struct ttm_operation_ctx *ctx,
>> -		      struct ttm_resource *new_reg)
>> -{
>> -	struct ttm_place placement_memtype = {
>> -		.fpfn = 0,
>> -		.lpfn = 0,
>> -		.mem_type = TTM_PL_TT,
>> -		.flags = 0
>> -	};
>> -	struct ttm_placement placement;
>> -	struct ttm_resource tmp_reg;
>> -	int ret;
>> -
>> -	placement.num_placement = placement.num_busy_placement = 1;
>> -	placement.placement = placement.busy_placement = &placement_memtype;
>> -
>> -	tmp_reg = *new_reg;
>> -	tmp_reg.mm_node = NULL;
>> -	ret = ttm_bo_mem_space(bo, &placement, &tmp_reg, ctx);
>> -	if (ret)
>> -		return ret;
>> -
>> -	ret = ttm_tt_populate(bo->bdev, bo->ttm, ctx);
>> -	if (ret)
>> -		goto out;
>> -
>> -	ret = nouveau_ttm_tt_bind(bo->bdev, bo->ttm, &tmp_reg);
>> -	if (ret)
>> -		goto out;
>> -
>> -	ret = nouveau_bo_move_m2mf(bo, true, ctx, &tmp_reg);
>> -	if (ret)
>> -		goto out;
>> -
>> -	ret = ttm_bo_wait_ctx(bo, ctx);
>> -	if (ret)
>> -		goto out;
>> -
>> -	nouveau_ttm_tt_unbind(bo->bdev, bo->ttm);
>> -	ttm_resource_free(bo, &bo->mem);
>> -	ttm_bo_assign_mem(bo, &tmp_reg);
>> -out:
>> -	ttm_resource_free(bo, &tmp_reg);
>> -	return ret;
>> -}
>> -
>> -static int
>> -nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict,
>> -		      struct ttm_operation_ctx *ctx,
>> -		      struct ttm_resource *new_reg)
>> -{
>> -	struct ttm_place placement_memtype = {
>> -		.fpfn = 0,
>> -		.lpfn = 0,
>> -		.mem_type = TTM_PL_TT,
>> -		.flags = 0
>> -	};
>> -	struct ttm_placement placement;
>> -	struct ttm_resource tmp_reg;
>> -	int ret;
>> -
>> -	placement.num_placement = placement.num_busy_placement = 1;
>> -	placement.placement = placement.busy_placement = &placement_memtype;
>> -
>> -	tmp_reg = *new_reg;
>> -	tmp_reg.mm_node = NULL;
>> -	ret = ttm_bo_mem_space(bo, &placement, &tmp_reg, ctx);
>> -	if (ret)
>> -		return ret;
>> -
>> -	ret = ttm_tt_populate(bo->bdev, bo->ttm, ctx);
>> -	if (unlikely(ret != 0))
>> -		return ret;
>> -
>> -	ret = nouveau_ttm_tt_bind(bo->bdev, bo->ttm, &tmp_reg);
>> -	if (unlikely(ret != 0))
>> -		return ret;
>> -
>> -	ttm_bo_assign_mem(bo, &tmp_reg);
>> -	ret = nouveau_bo_move_m2mf(bo, true, ctx, new_reg);
>> -	if (ret)
>> -		goto out;
>> -
>> -out:
>> -	ttm_resource_free(bo, &tmp_reg);
>> -	return ret;
>> -}
>> -
>>   static void
>>   nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, bool evict,
>>   		     struct ttm_resource *new_reg)
>> @@ -1024,7 +934,8 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo,
>>   static int
>>   nouveau_bo_move(struct ttm_buffer_object *bo, bool evict,
>>   		struct ttm_operation_ctx *ctx,
>> -		struct ttm_resource *new_reg)
>> +		struct ttm_resource *new_reg,
>> +		struct ttm_place *hop)
>>   {
>>   	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
>>   	struct nouveau_bo *nvbo = nouveau_bo(bo);
>> @@ -1032,6 +943,17 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict,
>>   	struct nouveau_drm_tile *new_tile = NULL;
>>   	int ret = 0;
>>   
>> +	if ((old_reg->mem_type == TTM_PL_SYSTEM &&
>> +	     new_reg->mem_type == TTM_PL_VRAM) ||
>> +	    (old_reg->mem_type == TTM_PL_VRAM &&
>> +	     new_reg->mem_type == TTM_PL_SYSTEM)) {
>> +		hop->fpfn = 0;
>> +		hop->lpfn = 0;
>> +		hop->mem_type = TTM_PL_TT;
>> +		hop->flags = 0;
>> +		return -EMULTIHOP;
>> +	}
>> +
>>   	if (new_reg->mem_type == TTM_PL_TT) {
>>   		ret = nouveau_ttm_tt_bind(bo->bdev, bo->ttm, new_reg);
>>   		if (ret)
>> @@ -1074,15 +996,8 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict,
>>   
>>   	/* Hardware assisted copy. */
>>   	if (drm->ttm.move) {
>> -		if (new_reg->mem_type == TTM_PL_SYSTEM)
>> -			ret = nouveau_bo_move_flipd(bo, evict, ctx,
>> -						    new_reg);
>> -		else if (old_reg->mem_type == TTM_PL_SYSTEM)
>> -			ret = nouveau_bo_move_flips(bo, evict, ctx,
>> -						    new_reg);
>> -		else
>> -			ret = nouveau_bo_move_m2mf(bo, evict, ctx,
>> -						   new_reg);
>> +		ret = nouveau_bo_move_m2mf(bo, evict, ctx,
>> +					   new_reg);
>>   		if (!ret)
>>   			goto out;
>>   	}
>> diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c
>> index b52a4563b47b..103e4f248f37 100644
>> --- a/drivers/gpu/drm/qxl/qxl_ttm.c
>> +++ b/drivers/gpu/drm/qxl/qxl_ttm.c
>> @@ -141,7 +141,8 @@ static void qxl_bo_move_notify(struct ttm_buffer_object *bo,
>>   
>>   static int qxl_bo_move(struct ttm_buffer_object *bo, bool evict,
>>   		       struct ttm_operation_ctx *ctx,
>> -		       struct ttm_resource *new_mem)
>> +		       struct ttm_resource *new_mem,
>> +		       struct ttm_place *hop)
>>   {
>>   	struct ttm_resource *old_mem = &bo->mem;
>>   	int ret;
>> diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
>> index 321c09d20c6c..ddb04a2dc25f 100644
>> --- a/drivers/gpu/drm/radeon/radeon_ttm.c
>> +++ b/drivers/gpu/drm/radeon/radeon_ttm.c
>> @@ -207,110 +207,27 @@ static int radeon_move_blit(struct ttm_buffer_object *bo,
>>   	return r;
>>   }
>>   
>> -static int radeon_move_vram_ram(struct ttm_buffer_object *bo,
>> -				bool evict,
>> -				struct ttm_operation_ctx *ctx,
>> -				struct ttm_resource *new_mem)
>> -{
>> -	struct ttm_resource *old_mem = &bo->mem;
>> -	struct ttm_resource tmp_mem;
>> -	struct ttm_place placements;
>> -	struct ttm_placement placement;
>> -	int r;
>> -
>> -	tmp_mem = *new_mem;
>> -	tmp_mem.mm_node = NULL;
>> -	placement.num_placement = 1;
>> -	placement.placement = &placements;
>> -	placement.num_busy_placement = 1;
>> -	placement.busy_placement = &placements;
>> -	placements.fpfn = 0;
>> -	placements.lpfn = 0;
>> -	placements.mem_type = TTM_PL_TT;
>> -	placements.flags = 0;
>> -	r = ttm_bo_mem_space(bo, &placement, &tmp_mem, ctx);
>> -	if (unlikely(r)) {
>> -		return r;
>> -	}
>> -
>> -	r = ttm_tt_populate(bo->bdev, bo->ttm, ctx);
>> -	if (unlikely(r)) {
>> -		goto out_cleanup;
>> -	}
>> -
>> -	r = radeon_ttm_tt_bind(bo->bdev, bo->ttm, &tmp_mem);
>> -	if (unlikely(r)) {
>> -		goto out_cleanup;
>> -	}
>> -	r = radeon_move_blit(bo, true, &tmp_mem, old_mem);
>> -	if (unlikely(r)) {
>> -		goto out_cleanup;
>> -	}
>> -	r = ttm_bo_wait_ctx(bo, ctx);
>> -	if (unlikely(r))
>> -		goto out_cleanup;
>> -
>> -	radeon_ttm_tt_unbind(bo->bdev, bo->ttm);
>> -	ttm_resource_free(bo, &bo->mem);
>> -	ttm_bo_assign_mem(bo, new_mem);
>> -out_cleanup:
>> -	ttm_resource_free(bo, &tmp_mem);
>> -	return r;
>> -}
>> -
>> -static int radeon_move_ram_vram(struct ttm_buffer_object *bo,
>> -				bool evict,
>> -				struct ttm_operation_ctx *ctx,
>> -				struct ttm_resource *new_mem)
>> -{
>> -	struct ttm_resource *old_mem = &bo->mem;
>> -	struct ttm_resource tmp_mem;
>> -	struct ttm_placement placement;
>> -	struct ttm_place placements;
>> -	int r;
>> -
>> -	tmp_mem = *new_mem;
>> -	tmp_mem.mm_node = NULL;
>> -	placement.num_placement = 1;
>> -	placement.placement = &placements;
>> -	placement.num_busy_placement = 1;
>> -	placement.busy_placement = &placements;
>> -	placements.fpfn = 0;
>> -	placements.lpfn = 0;
>> -	placements.mem_type = TTM_PL_TT;
>> -	placements.flags = 0;
>> -	r = ttm_bo_mem_space(bo, &placement, &tmp_mem, ctx);
>> -	if (unlikely(r)) {
>> -		return r;
>> -	}
>> -
>> -	r = ttm_tt_populate(bo->bdev, bo->ttm, ctx);
>> -	if (unlikely(r))
>> -		goto out_cleanup;
>> -
>> -	r = radeon_ttm_tt_bind(bo->bdev, bo->ttm, &tmp_mem);
>> -	if (unlikely(r))
>> -		goto out_cleanup;
>> -
>> -	ttm_bo_assign_mem(bo, &tmp_mem);
>> -	r = radeon_move_blit(bo, true, new_mem, old_mem);
>> -	if (unlikely(r)) {
>> -		goto out_cleanup;
>> -	}
>> -out_cleanup:
>> -	ttm_resource_free(bo, &tmp_mem);
>> -	return r;
>> -}
>> -
>>   static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict,
>>   			  struct ttm_operation_ctx *ctx,
>> -			  struct ttm_resource *new_mem)
>> +			  struct ttm_resource *new_mem,
>> +			  struct ttm_place *hop)
>>   {
>>   	struct radeon_device *rdev;
>>   	struct radeon_bo *rbo;
>>   	struct ttm_resource *old_mem = &bo->mem;
>>   	int r;
>>   
>> +	if ((old_mem->mem_type == TTM_PL_SYSTEM &&
>> +	     new_mem->mem_type == TTM_PL_VRAM) ||
>> +	    (old_mem->mem_type == TTM_PL_VRAM &&
>> +	     new_mem->mem_type == TTM_PL_SYSTEM)) {
>> +		hop->fpfn = 0;
>> +		hop->lpfn = 0;
>> +		hop->mem_type = TTM_PL_TT;
>> +		hop->flags = 0;
>> +		return -EMULTIHOP;
>> +	}
>> +
>>   	if (new_mem->mem_type == TTM_PL_TT) {
>>   		r = radeon_ttm_tt_bind(bo->bdev, bo->ttm, new_mem);
>>   		if (r)
>> @@ -351,17 +268,8 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict,
>>   		goto memcpy;
>>   	}
>>   
>> -	if (old_mem->mem_type == TTM_PL_VRAM &&
>> -	    new_mem->mem_type == TTM_PL_SYSTEM) {
>> -		r = radeon_move_vram_ram(bo, evict, ctx, new_mem);
>> -	} else if (old_mem->mem_type == TTM_PL_SYSTEM &&
>> -		   new_mem->mem_type == TTM_PL_VRAM) {
>> -		r = radeon_move_ram_vram(bo, evict, ctx, new_mem);
>> -	} else {
>> -		r = radeon_move_blit(bo, evict,
>> -				     new_mem, old_mem);
>> -	}
>> -
>> +	r = radeon_move_blit(bo, evict,
>> +			     new_mem, old_mem);
>>   	if (r) {
>>   memcpy:
>>   		r = ttm_bo_move_memcpy(bo, ctx, new_mem);
>> diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
>> index 5b411252a857..a8830fdf8bc6 100644
>> --- a/drivers/gpu/drm/ttm/ttm_bo.c
>> +++ b/drivers/gpu/drm/ttm/ttm_bo.c
>> @@ -231,7 +231,8 @@ EXPORT_SYMBOL(ttm_bo_bulk_move_lru_tail);
>>   
>>   static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
>>   				  struct ttm_resource *mem, bool evict,
>> -				  struct ttm_operation_ctx *ctx)
>> +				  struct ttm_operation_ctx *ctx,
>> +				  struct ttm_place *hop)
>>   {
>>   	struct ttm_bo_device *bdev = bo->bdev;
>>   	struct ttm_resource_manager *old_man = ttm_manager_type(bdev, bo->mem.mem_type);
>> @@ -259,9 +260,12 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
>>   		}
>>   	}
>>   
>> -	ret = bdev->driver->move(bo, evict, ctx, mem);
>> -	if (ret)
>> +	ret = bdev->driver->move(bo, evict, ctx, mem, hop);
>> +	if (ret) {
>> +		if (ret == -EMULTIHOP)
>> +			return ret;
>>   		goto out_err;
>> +	}
>>   
>>   	ctx->bytes_moved += bo->num_pages << PAGE_SHIFT;
>>   	return 0;
>> @@ -596,7 +600,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo,
>>   		goto out;
>>   	}
>>   
>> -	ret = ttm_bo_handle_move_mem(bo, &evict_mem, true, ctx);
>> +	ret = ttm_bo_handle_move_mem(bo, &evict_mem, true, ctx, NULL);
>>   	if (unlikely(ret)) {
>>   		if (ret != -ERESTARTSYS)
>>   			pr_err("Buffer eviction failed\n");
>> @@ -936,11 +940,39 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
>>   }
>>   EXPORT_SYMBOL(ttm_bo_mem_space);
>>   
>> +static int ttm_bo_bounce_temp_buffer(struct ttm_buffer_object *bo,
>> +				     struct ttm_resource *mem,
>> +				     struct ttm_operation_ctx *ctx,
>> +				     struct ttm_place *hop)
>> +{
>> +	struct ttm_placement hop_placement;
>> +	int ret;
>> +	struct ttm_resource hop_mem = *mem;
>> +
>> +	hop_mem.mm_node = NULL;
>> +	hop_mem.mem_type = TTM_PL_SYSTEM;
>> +	hop_mem.placement = 0;
>> +
>> +	hop_placement.num_placement = hop_placement.num_busy_placement = 1;
>> +	hop_placement.placement = hop_placement.busy_placement = hop;
>> +
>> +	/* find space in the bounce domain */
>> +	ret = ttm_bo_mem_space(bo, &hop_placement, &hop_mem, ctx);
>> +	if (ret)
>> +		return ret;
>> +	/* move to the bounce domain */
>> +	ret = ttm_bo_handle_move_mem(bo, &hop_mem, false, ctx, NULL);
>> +	if (ret)
>> +		return ret;
>> +	return 0;
>> +}
>> +
>>   static int ttm_bo_move_buffer(struct ttm_buffer_object *bo,
>>   			      struct ttm_placement *placement,
>>   			      struct ttm_operation_ctx *ctx)
>>   {
>>   	int ret = 0;
>> +	struct ttm_place hop = {};
>>   	struct ttm_resource mem;
>>   
>>   	dma_resv_assert_held(bo->base.resv);
>> @@ -954,12 +986,25 @@ static int ttm_bo_move_buffer(struct ttm_buffer_object *bo,
>>   
>>   	/*
>>   	 * Determine where to move the buffer.
>> +	 *
>> +	 * If driver determines move is going to need
>> +	 * an extra step then it will return -EMULTIHOP
>> +	 * and the buffer will be moved to the temporary
>> +	 * stop and the driver will be called to make
>> +	 * the second hop.
>>   	 */
>> +bounce:
>>   	ret = ttm_bo_mem_space(bo, placement, &mem, ctx);
>>   	if (ret)
>> -		goto out_unlock;
>> -	ret = ttm_bo_handle_move_mem(bo, &mem, false, ctx);
>> -out_unlock:
>> +		return ret;
>> +	ret = ttm_bo_handle_move_mem(bo, &mem, false, ctx, &hop);
>> +	if (ret == -EMULTIHOP) {
>> +		ret = ttm_bo_bounce_temp_buffer(bo, &mem, ctx, &hop);
>> +		if (ret)
>> +			return ret;
>> +		/* try and move to final place now. */
>> +		goto bounce;
>> +	}
>>   	if (ret)
>>   		ttm_resource_free(bo, &mem);
>>   	return ret;
>> @@ -1435,7 +1480,7 @@ int ttm_bo_swapout(struct ttm_operation_ctx *ctx)
>>   		evict_mem.placement = 0;
>>   		evict_mem.mem_type = TTM_PL_SYSTEM;
>>   
>> -		ret = ttm_bo_handle_move_mem(bo, &evict_mem, true, &ctx);
>> +		ret = ttm_bo_handle_move_mem(bo, &evict_mem, true, &ctx, NULL);
>>   		if (unlikely(ret != 0))
>>   			goto out;
>>   	}
>> @@ -1481,4 +1526,3 @@ void ttm_bo_tt_destroy(struct ttm_buffer_object *bo)
>>   	ttm_tt_destroy(bo->bdev, bo->ttm);
>>   	bo->ttm = NULL;
>>   }
>> -
>> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
>> index 88be48ad0344..d48b70605a56 100644
>> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
>> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
>> @@ -731,7 +731,8 @@ static void vmw_swap_notify(struct ttm_buffer_object *bo)
>>   static int vmw_move(struct ttm_buffer_object *bo,
>>   		    bool evict,
>>   		    struct ttm_operation_ctx *ctx,
>> -		    struct ttm_resource *new_mem)
>> +		    struct ttm_resource *new_mem,
>> +		    struct ttm_place *hop)
>>   {
>>   	struct ttm_resource_manager *old_man = ttm_manager_type(bo->bdev, bo->mem.mem_type);
>>   	struct ttm_resource_manager *new_man = ttm_manager_type(bo->bdev, new_mem->mem_type);
>> diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
>> index 29f6a1d1c853..e4eab7a45ace 100644
>> --- a/include/drm/ttm/ttm_bo_driver.h
>> +++ b/include/drm/ttm/ttm_bo_driver.h
>> @@ -133,12 +133,15 @@ struct ttm_bo_driver {
>>   	 * the graphics address space
>>   	 * @ctx: context for this move with parameters
>>   	 * @new_mem: the new memory region receiving the buffer
>> +	 @ @hop: placement for driver directed intermediate hop
>>   	 *
>>   	 * Move a buffer between two memory regions.
>> +	 * Returns errno -EMULTIHOP if driver requests a hop
>>   	 */
>>   	int (*move)(struct ttm_buffer_object *bo, bool evict,
>>   		    struct ttm_operation_ctx *ctx,
>> -		    struct ttm_resource *new_mem);
>> +		    struct ttm_resource *new_mem,
>> +		    struct ttm_place *hop);
>>   
>>   	/**
>>   	 * struct ttm_bo_driver_member verify_access
>> -- 
>> 2.27.0
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel at lists.freedesktop.org
>> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Fdri-devel&data=04%7C01%7Cchristian.koenig%40amd.com%7Ce4ee898f6eb94250ce3008d8759bfa2c%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637388660089425780%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=QHhSO95cYUjBsm%2FP%2FOUNlaQK56NLp0zHUw2QuAoZ0tY%3D&reserved=0



More information about the dri-devel mailing list