Skip to content

Commit cc941c7

Browse files
drm/ttm: improve idle/busy handling v5
Previously we would never try to move a BO into the preferred placements when it ever landed in a busy placement since those were considered compatible. Rework the whole handling and finally unify the idle and busy handling. ttm_bo_validate() is now responsible to try idle placement first and then use the busy placement if that didn't worked. Drawback is that we now always try the idle placement first for each validation which might cause some additional CPU overhead on overcommit. v2: fix kerneldoc warning and coding style v3: take care of XE as well v4: keep the ttm_bo_mem_space functionality as it is for now, only add new handling for ttm_bo_validate as suggested by Thomas v5: fix bug pointed out by Matthew Signed-off-by: Christian König <[email protected]> Reviewed-by: Zack Rusin <[email protected]> v3 Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] Reviewed-by: Thomas Hellström <[email protected]>
1 parent 6f6eebc commit cc941c7

File tree

3 files changed

+121
-129
lines changed

3 files changed

+121
-129
lines changed

drivers/gpu/drm/ttm/ttm_bo.c

Lines changed: 107 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -724,64 +724,36 @@ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo,
724724
return ret;
725725
}
726726

727-
/*
728-
* Repeatedly evict memory from the LRU for @mem_type until we create enough
729-
* space, or we've evicted everything and there isn't enough space.
730-
*/
731-
static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo,
732-
const struct ttm_place *place,
733-
struct ttm_resource **mem,
734-
struct ttm_operation_ctx *ctx)
735-
{
736-
struct ttm_device *bdev = bo->bdev;
737-
struct ttm_resource_manager *man;
738-
struct ww_acquire_ctx *ticket;
739-
int ret;
740-
741-
man = ttm_manager_type(bdev, place->mem_type);
742-
ticket = dma_resv_locking_ctx(bo->base.resv);
743-
do {
744-
ret = ttm_resource_alloc(bo, place, mem);
745-
if (likely(!ret))
746-
break;
747-
if (unlikely(ret != -ENOSPC))
748-
return ret;
749-
ret = ttm_mem_evict_first(bdev, man, place, ctx,
750-
ticket);
751-
if (unlikely(ret != 0))
752-
return ret;
753-
} while (1);
754-
755-
return ttm_bo_add_move_fence(bo, man, *mem, ctx->no_wait_gpu);
756-
}
757-
758727
/**
759-
* ttm_bo_mem_space
728+
* ttm_bo_alloc_resource - Allocate backing store for a BO
760729
*
761-
* @bo: Pointer to a struct ttm_buffer_object. the data of which
762-
* we want to allocate space for.
763-
* @placement: Proposed new placement for the buffer object.
764-
* @mem: A struct ttm_resource.
730+
* @bo: Pointer to a struct ttm_buffer_object of which we want a resource for
731+
* @placement: Proposed new placement for the buffer object
765732
* @ctx: if and how to sleep, lock buffers and alloc memory
733+
* @force_space: If we should evict buffers to force space
734+
* @res: The resulting struct ttm_resource.
766735
*
767-
* Allocate memory space for the buffer object pointed to by @bo, using
768-
* the placement flags in @placement, potentially evicting other idle buffer objects.
769-
* This function may sleep while waiting for space to become available.
736+
* Allocates a resource for the buffer object pointed to by @bo, using the
737+
* placement flags in @placement, potentially evicting other buffer objects when
738+
* @force_space is true.
739+
* This function may sleep while waiting for resources to become available.
770740
* Returns:
771-
* -EBUSY: No space available (only if no_wait == 1).
741+
* -EBUSY: No space available (only if no_wait == true).
772742
* -ENOSPC: Could not allocate space for the buffer object, either due to
773743
* fragmentation or concurrent allocators.
774744
* -ERESTARTSYS: An interruptible sleep was interrupted by a signal.
775745
*/
776-
int ttm_bo_mem_space(struct ttm_buffer_object *bo,
777-
struct ttm_placement *placement,
778-
struct ttm_resource **mem,
779-
struct ttm_operation_ctx *ctx)
746+
static int ttm_bo_alloc_resource(struct ttm_buffer_object *bo,
747+
struct ttm_placement *placement,
748+
struct ttm_operation_ctx *ctx,
749+
bool force_space,
750+
struct ttm_resource **res)
780751
{
781752
struct ttm_device *bdev = bo->bdev;
782-
bool type_found = false;
753+
struct ww_acquire_ctx *ticket;
783754
int i, ret;
784755

756+
ticket = dma_resv_locking_ctx(bo->base.resv);
785757
ret = dma_resv_reserve_fences(bo->base.resv, 1);
786758
if (unlikely(ret))
787759
return ret;
@@ -790,98 +762,73 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
790762
const struct ttm_place *place = &placement->placement[i];
791763
struct ttm_resource_manager *man;
792764

793-
if (place->flags & TTM_PL_FLAG_FALLBACK)
794-
continue;
795-
796765
man = ttm_manager_type(bdev, place->mem_type);
797766
if (!man || !ttm_resource_manager_used(man))
798767
continue;
799768

800-
type_found = true;
801-
ret = ttm_resource_alloc(bo, place, mem);
802-
if (ret == -ENOSPC)
769+
if (place->flags & (force_space ? TTM_PL_FLAG_DESIRED :
770+
TTM_PL_FLAG_FALLBACK))
771+
continue;
772+
773+
do {
774+
ret = ttm_resource_alloc(bo, place, res);
775+
if (unlikely(ret && ret != -ENOSPC))
776+
return ret;
777+
if (likely(!ret) || !force_space)
778+
break;
779+
780+
ret = ttm_mem_evict_first(bdev, man, place, ctx,
781+
ticket);
782+
if (unlikely(ret == -EBUSY))
783+
break;
784+
if (unlikely(ret))
785+
return ret;
786+
} while (1);
787+
if (ret)
803788
continue;
804-
if (unlikely(ret))
805-
goto error;
806789

807-
ret = ttm_bo_add_move_fence(bo, man, *mem, ctx->no_wait_gpu);
790+
ret = ttm_bo_add_move_fence(bo, man, *res, ctx->no_wait_gpu);
808791
if (unlikely(ret)) {
809-
ttm_resource_free(bo, mem);
792+
ttm_resource_free(bo, res);
810793
if (ret == -EBUSY)
811794
continue;
812795

813-
goto error;
796+
return ret;
814797
}
815798
return 0;
816799
}
817800

818-
for (i = 0; i < placement->num_placement; ++i) {
819-
const struct ttm_place *place = &placement->placement[i];
820-
struct ttm_resource_manager *man;
821-
822-
if (place->flags & TTM_PL_FLAG_DESIRED)
823-
continue;
824-
825-
man = ttm_manager_type(bdev, place->mem_type);
826-
if (!man || !ttm_resource_manager_used(man))
827-
continue;
828-
829-
type_found = true;
830-
ret = ttm_bo_mem_force_space(bo, place, mem, ctx);
831-
if (likely(!ret))
832-
return 0;
833-
834-
if (ret && ret != -EBUSY)
835-
goto error;
836-
}
837-
838-
ret = -ENOSPC;
839-
if (!type_found) {
840-
pr_err(TTM_PFX "No compatible memory type found\n");
841-
ret = -EINVAL;
842-
}
843-
844-
error:
845-
return ret;
801+
return -ENOSPC;
846802
}
847-
EXPORT_SYMBOL(ttm_bo_mem_space);
848803

849-
static int ttm_bo_move_buffer(struct ttm_buffer_object *bo,
850-
struct ttm_placement *placement,
851-
struct ttm_operation_ctx *ctx)
804+
/*
805+
* ttm_bo_mem_space - Wrapper around ttm_bo_alloc_resource
806+
*
807+
* @bo: Pointer to a struct ttm_buffer_object of which we want a resource for
808+
* @placement: Proposed new placement for the buffer object
809+
* @res: The resulting struct ttm_resource.
810+
* @ctx: if and how to sleep, lock buffers and alloc memory
811+
*
812+
* Tries both idle allocation and forcefully eviction of buffers. See
813+
* ttm_bo_alloc_resource for details.
814+
*/
815+
int ttm_bo_mem_space(struct ttm_buffer_object *bo,
816+
struct ttm_placement *placement,
817+
struct ttm_resource **res,
818+
struct ttm_operation_ctx *ctx)
852819
{
853-
struct ttm_resource *mem;
854-
struct ttm_place hop;
820+
bool force_space = false;
855821
int ret;
856822

857-
dma_resv_assert_held(bo->base.resv);
823+
do {
824+
ret = ttm_bo_alloc_resource(bo, placement, ctx,
825+
force_space, res);
826+
force_space = !force_space;
827+
} while (ret == -ENOSPC && force_space);
858828

859-
/*
860-
* Determine where to move the buffer.
861-
*
862-
* If driver determines move is going to need
863-
* an extra step then it will return -EMULTIHOP
864-
* and the buffer will be moved to the temporary
865-
* stop and the driver will be called to make
866-
* the second hop.
867-
*/
868-
ret = ttm_bo_mem_space(bo, placement, &mem, ctx);
869-
if (ret)
870-
return ret;
871-
bounce:
872-
ret = ttm_bo_handle_move_mem(bo, mem, false, ctx, &hop);
873-
if (ret == -EMULTIHOP) {
874-
ret = ttm_bo_bounce_temp_buffer(bo, &mem, ctx, &hop);
875-
if (ret)
876-
goto out;
877-
/* try and move to final place now. */
878-
goto bounce;
879-
}
880-
out:
881-
if (ret)
882-
ttm_resource_free(bo, &mem);
883829
return ret;
884830
}
831+
EXPORT_SYMBOL(ttm_bo_mem_space);
885832

886833
/**
887834
* ttm_bo_validate
@@ -902,6 +849,9 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
902849
struct ttm_placement *placement,
903850
struct ttm_operation_ctx *ctx)
904851
{
852+
struct ttm_resource *res;
853+
struct ttm_place hop;
854+
bool force_space;
905855
int ret;
906856

907857
dma_resv_assert_held(bo->base.resv);
@@ -912,20 +862,53 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
912862
if (!placement->num_placement)
913863
return ttm_bo_pipeline_gutting(bo);
914864

915-
/* Check whether we need to move buffer. */
916-
if (bo->resource && ttm_resource_compatible(bo->resource, placement))
917-
return 0;
865+
force_space = false;
866+
do {
867+
/* Check whether we need to move buffer. */
868+
if (bo->resource &&
869+
ttm_resource_compatible(bo->resource, placement,
870+
force_space))
871+
return 0;
918872

919-
/* Moving of pinned BOs is forbidden */
920-
if (bo->pin_count)
921-
return -EINVAL;
873+
/* Moving of pinned BOs is forbidden */
874+
if (bo->pin_count)
875+
return -EINVAL;
876+
877+
/*
878+
* Determine where to move the buffer.
879+
*
880+
* If driver determines move is going to need
881+
* an extra step then it will return -EMULTIHOP
882+
* and the buffer will be moved to the temporary
883+
* stop and the driver will be called to make
884+
* the second hop.
885+
*/
886+
ret = ttm_bo_alloc_resource(bo, placement, ctx, force_space,
887+
&res);
888+
force_space = !force_space;
889+
if (ret == -ENOSPC)
890+
continue;
891+
if (ret)
892+
return ret;
893+
894+
bounce:
895+
ret = ttm_bo_handle_move_mem(bo, res, false, ctx, &hop);
896+
if (ret == -EMULTIHOP) {
897+
ret = ttm_bo_bounce_temp_buffer(bo, &res, ctx, &hop);
898+
/* try and move to final place now. */
899+
if (!ret)
900+
goto bounce;
901+
}
902+
if (ret) {
903+
ttm_resource_free(bo, &res);
904+
return ret;
905+
}
906+
907+
} while (ret && force_space);
922908

923-
ret = ttm_bo_move_buffer(bo, placement, ctx);
924909
/* For backward compatibility with userspace */
925910
if (ret == -ENOSPC)
926911
return -ENOMEM;
927-
if (ret)
928-
return ret;
929912

930913
/*
931914
* We might need to add a TTM.

drivers/gpu/drm/ttm/ttm_resource.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -295,11 +295,13 @@ bool ttm_resource_intersects(struct ttm_device *bdev,
295295
*
296296
* @res: the resource to check
297297
* @placement: the placement to check against
298+
* @evicting: true if the caller is doing evictions
298299
*
299300
* Returns true if the placement is compatible.
300301
*/
301302
bool ttm_resource_compatible(struct ttm_resource *res,
302-
struct ttm_placement *placement)
303+
struct ttm_placement *placement,
304+
bool evicting)
303305
{
304306
struct ttm_buffer_object *bo = res->bo;
305307
struct ttm_device *bdev = bo->bdev;
@@ -315,14 +317,20 @@ bool ttm_resource_compatible(struct ttm_resource *res,
315317
if (res->mem_type != place->mem_type)
316318
continue;
317319

320+
if (place->flags & (evicting ? TTM_PL_FLAG_DESIRED :
321+
TTM_PL_FLAG_FALLBACK))
322+
continue;
323+
324+
if (place->flags & TTM_PL_FLAG_CONTIGUOUS &&
325+
!(res->placement & TTM_PL_FLAG_CONTIGUOUS))
326+
continue;
327+
318328
man = ttm_manager_type(bdev, res->mem_type);
319329
if (man->func->compatible &&
320330
!man->func->compatible(man, res, place, bo->base.size))
321331
continue;
322332

323-
if ((!(place->flags & TTM_PL_FLAG_CONTIGUOUS) ||
324-
(res->placement & TTM_PL_FLAG_CONTIGUOUS)))
325-
return true;
333+
return true;
326334
}
327335
return false;
328336
}

include/drm/ttm/ttm_resource.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,8 @@ bool ttm_resource_intersects(struct ttm_device *bdev,
366366
const struct ttm_place *place,
367367
size_t size);
368368
bool ttm_resource_compatible(struct ttm_resource *res,
369-
struct ttm_placement *placement);
369+
struct ttm_placement *placement,
370+
bool evicting);
370371
void ttm_resource_set_bo(struct ttm_resource *res,
371372
struct ttm_buffer_object *bo);
372373

0 commit comments

Comments
 (0)