When VRAM is nearly full, the Buddy allocator makes tradeoffs and it may place BOs in a way that they cross 256M segments.
Move the BO to GTT when this eventuality is detected. Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/4800 Signed-off-by: Timur Kristóf <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index a106c7e77e26..fb49bd53bd00 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -977,6 +977,7 @@ u32 amdgpu_ttm_fill_gart_256M_placements(struct ttm_buffer_object *bo, u32 max_placements) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); + const u64 sz = adev->gmc.gart_size; u32 i; /* Fill the placements array with 256M segments, starting from highest. */ @@ -984,7 +985,7 @@ u32 amdgpu_ttm_fill_gart_256M_placements(struct ttm_buffer_object *bo, if (i * SZ_256M >= adev->gmc.gart_size) break; - placements[i].lpfn = (adev->gmc.gart_size - i * SZ_256M) >> PAGE_SHIFT; + placements[i].lpfn = MIN(ALIGN(sz, SZ_256M) - i * SZ_256M, sz) >> PAGE_SHIFT; placements[i].fpfn = ALIGN_DOWN(placements[i].lpfn - 1, SZ_256M >> PAGE_SHIFT); placements[i].mem_type = TTM_PL_TT; placements[i].flags = bo->resource->placement; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index 993957927782..53f810c2a5fb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -617,6 +617,27 @@ static int amdgpu_uvd_cs_pass1(struct amdgpu_uvd_cs_ctx *ctx) amdgpu_uvd_force_into_uvd_segment(bo); r = ttm_bo_validate(&bo->tbo, &bo->placement, &tctx); + if (r) + return r; + + /* Check if the BO placement crosses a 256M segment. */ + if ((amdgpu_bo_gpu_offset(bo) >> 28) != + ((amdgpu_bo_gpu_offset(bo) + amdgpu_bo_size(bo)) >> 28)) { + /* There is not enough memory for correct placement of FB/MSG BOs. */ + if (cmd == 0x0 || cmd == 0x3) + return -ENOMEM; + + /* GTT->GTT moves are not implemented yet. */ + if (bo->tbo.resource->mem_type != TTM_PL_VRAM) + return -ENOMEM; + + /* Try to move the BO from VRAM to GART into a 256M segment. */ + amdgpu_ttm_fill_gart_256M_placements(&bo->tbo, + bo->placements, + ARRAY_SIZE(bo->placements)); + + r = ttm_bo_validate(&bo->tbo, &bo->placement, &tctx); + } } return r; -- 2.54.0
