From 92a9ace7f8b04f5597e8f2f6559ae3c18688a63d Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Thu, 18 Nov 2010 13:48:16 -0500 Subject: [PATCH] drm/radeon/kms: forbid allocating bo bigger than VRAM or GTT (fdo 31708) Forbid allocating buffer bigger than VRAM or GTT, also properly set lpfn field of placement if VRAM is too small. Signed-off-by: Jerome Glisse --- drivers/gpu/drm/radeon/radeon.h | 2 +- drivers/gpu/drm/radeon/radeon_object.c | 19 ++++++++++++++----- drivers/gpu/drm/radeon/radeon_ttm.c | 6 +++--- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 73f600d..2068cf4 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1361,7 +1361,7 @@ extern void radeon_surface_init(struct radeon_device *rdev); extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data); extern void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable); extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable); -extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain); +extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain, u32 size); extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo); extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base); extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 8eb1834..a09d076 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -64,12 +64,18 @@ bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo) return false; } -void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) +void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain, u32 size) { u32 c = 0; rbo->placement.fpfn = 0; rbo->placement.lpfn = rbo->rdev->mc.active_vram_size >> PAGE_SHIFT; + /* size bigger than vram directly fallback to GTT*/ + if (size >= rbo->rdev->mc.active_vram_size) { + rbo->placement.lpfn = rbo->rdev->mc.gtt_size >> PAGE_SHIFT; + if (!(domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_CPU))) + domain |= RADEON_GEM_DOMAIN_GTT; + } rbo->placement.placement = rbo->placements; rbo->placement.busy_placement = rbo->placements; if (domain & RADEON_GEM_DOMAIN_VRAM) @@ -102,6 +108,9 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj, type = ttm_bo_type_device; } *bo_ptr = NULL; + if (size >= rdev->mc.active_vram_size && size >= rdev->mc.gtt_size) { + return -ENOMEM; + } retry: bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); @@ -111,7 +120,7 @@ retry: bo->gobj = gobj; bo->surface_reg = -1; INIT_LIST_HEAD(&bo->list); - radeon_ttm_placement_from_domain(bo, domain); + radeon_ttm_placement_from_domain(bo, domain, size); /* Kernel allocation are uninterruptible */ mutex_lock(&rdev->vram_mutex); r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type, @@ -197,7 +206,7 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr) *gpu_addr = radeon_bo_gpu_offset(bo); return 0; } - radeon_ttm_placement_from_domain(bo, domain); + radeon_ttm_placement_from_domain(bo, domain, bo->tbo.num_pages << PAGE_SHIFT); if (domain == RADEON_GEM_DOMAIN_VRAM) { /* force to pin into visible video ram */ bo->placement.lpfn = bo->rdev->mc.visible_vram_size >> PAGE_SHIFT; @@ -343,7 +352,7 @@ int radeon_bo_list_validate(struct list_head *head) domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain; retry: - radeon_ttm_placement_from_domain(bo, domain); + radeon_ttm_placement_from_domain(bo, domain, bo->tbo.num_pages << PAGE_SHIFT); r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false, false); if (unlikely(r)) { @@ -535,7 +544,7 @@ int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) offset = bo->mem.start << PAGE_SHIFT; if ((offset + size) > rdev->mc.visible_vram_size) { /* hurrah the memory is not visible ! */ - radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM); + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM, bo->num_pages << PAGE_SHIFT); rbo->placement.lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT; r = ttm_bo_validate(bo, &rbo->placement, false, true, false); if (unlikely(r != 0)) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 01c2c73..8695319 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -207,13 +207,13 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo, switch (bo->mem.mem_type) { case TTM_PL_VRAM: if (rbo->rdev->cp.ready == false) - radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU); + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU, bo->num_pages << PAGE_SHIFT); else - radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT, bo->num_pages << PAGE_SHIFT); break; case TTM_PL_TT: default: - radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU); + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU, bo->num_pages << PAGE_SHIFT); } *placement = rbo->placement; } -- 1.7.1