diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 7f9710502bcc..78362e09cc51 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -205,7 +205,44 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, case TTM_PL_VRAM: if (adev->mman.buffer_funcs_ring->ready == false) { amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_CPU); + } else if (adev->mc.visible_vram_size < adev->mc.real_vram_size) { + unsigned fpfn = adev->mc.visible_vram_size >> PAGE_SHIFT; + int i; + + if (bo->mem.start >= fpfn) { + struct drm_mm_node *node = bo->mem.mm_node; + unsigned long pages_left; + + for (pages_left = bo->mem.num_pages; pages_left; + pages_left -= node->size, node++) { + if (node->start < fpfn) + break; + } + + if (!pages_left) + goto gtt; + } + + /* Try evicting to the CPU inaccessible part of VRAM + * first, but only set GTT as busy placement, so this + * BO will be evicted to GTT rather than causing other + * BOs to be evicted from VRAM + */ + amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_VRAM | + AMDGPU_GEM_DOMAIN_GTT); + abo->placement.num_busy_placement = 0; + for (i = 0; i < abo->placement.num_placement; i++) { + if (abo->placements[i].flags & TTM_PL_FLAG_VRAM) { + if (abo->placements[i].fpfn < fpfn) + abo->placements[i].fpfn = fpfn; + } else { + abo->placement.busy_placement = + &abo->placements[i]; + abo->placement.num_busy_placement = 1; + } + } } else { +gtt: amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT); for (i = 0; i < abo->placement.num_placement; ++i) { if (!(abo->placements[i].flags &