GART and VRAM size limits need to be a power of two. Fix values greater than 1GB and simplify those checks a bit.
v2: also fix radeon_vram_limit usage, and simplify test even more.
Signed-off-by: Christian König deathsimple@vodafone.de --- drivers/gpu/drm/radeon/radeon_device.c | 60 +++++++++++++------------------- 1 file changed, 24 insertions(+), 36 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index bd13ca0..01ac531 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -355,6 +355,8 @@ int radeon_wb_init(struct radeon_device *rdev) */ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base) { + uint64_t limit = (uint64_t)radeon_vram_limit << 20; + mc->vram_start = base; if (mc->mc_vram_size > (0xFFFFFFFF - base + 1)) { dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); @@ -368,8 +370,8 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 mc->mc_vram_size = mc->aper_size; } mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; - if (radeon_vram_limit && radeon_vram_limit < mc->real_vram_size) - mc->real_vram_size = radeon_vram_limit; + if (limit && limit < mc->real_vram_size) + mc->real_vram_size = limit; dev_info(rdev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n", mc->mc_vram_size >> 20, mc->vram_start, mc->vram_end, mc->real_vram_size >> 20); @@ -835,6 +837,19 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state) }
/** + * radeon_check_pot_argument - check that argument is a power of two + * + * @arg: value to check + * + * Validates that a certain argument is a power of two (all asics). + * Returns true if argument is valid. + */ +static bool radeon_ckeck_pot_argument(int arg) +{ + return (arg & (arg - 1)) == 0; +} + +/** * radeon_check_arguments - validate module params * * @rdev: radeon_device pointer @@ -845,52 +860,25 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state) static void radeon_check_arguments(struct radeon_device *rdev) { /* vramlimit must be a power of two */ - switch (radeon_vram_limit) { - case 0: - case 4: - case 8: - case 16: - case 32: - case 64: - case 128: - case 256: - case 512: - case 1024: - case 2048: - case 4096: - break; - default: + if (!radeon_ckeck_pot_argument(radeon_vram_limit)) { dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n", radeon_vram_limit); radeon_vram_limit = 0; - break; } - radeon_vram_limit = radeon_vram_limit << 20; + /* gtt size must be power of two and greater or equal to 32M */ - switch (radeon_gart_size) { - case 4: - case 8: - case 16: + if (radeon_gart_size < 32) { dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n", radeon_gart_size); radeon_gart_size = 512; - break; - case 32: - case 64: - case 128: - case 256: - case 512: - case 1024: - case 2048: - case 4096: - break; - default: + + } else if (!radeon_ckeck_pot_argument(radeon_gart_size)) { dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n", radeon_gart_size); radeon_gart_size = 512; - break; } - rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; + rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20; + /* AGP mode can only be -1, 1, 2, 4, 8 */ switch (radeon_agpmode) { case -1:
When allocating more than 2GB of GART the array of pages gets to big for kzalloc, use vzalloc instead.
Signed-off-by: Christian König deathsimple@vodafone.de Reviewed-by: Michel Dänzer michel.daenzer@amd.com --- drivers/gpu/drm/radeon/radeon_gart.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 9a64f8c..631973d 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -355,14 +355,13 @@ int radeon_gart_init(struct radeon_device *rdev) DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n", rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages); /* Allocate pages table */ - rdev->gart.pages = kzalloc(sizeof(void *) * rdev->gart.num_cpu_pages, - GFP_KERNEL); + rdev->gart.pages = vzalloc(sizeof(void *) * rdev->gart.num_cpu_pages); if (rdev->gart.pages == NULL) { radeon_gart_fini(rdev); return -ENOMEM; } - rdev->gart.pages_addr = kzalloc(sizeof(dma_addr_t) * - rdev->gart.num_cpu_pages, GFP_KERNEL); + rdev->gart.pages_addr = vzalloc(sizeof(dma_addr_t) * + rdev->gart.num_cpu_pages); if (rdev->gart.pages_addr == NULL) { radeon_gart_fini(rdev); return -ENOMEM; @@ -388,8 +387,8 @@ void radeon_gart_fini(struct radeon_device *rdev) radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages); } rdev->gart.ready = false; - kfree(rdev->gart.pages); - kfree(rdev->gart.pages_addr); + vfree(rdev->gart.pages); + vfree(rdev->gart.pages_addr); rdev->gart.pages = NULL; rdev->gart.pages_addr = NULL;
Driver internal users shouldn't be limited in their allocation size.
Signed-off-by: Christian König deathsimple@vodafone.de Reviewed-by: Michel Dänzer michel.daenzer@amd.com --- drivers/gpu/drm/radeon/radeon_gem.c | 10 ++++++++++ drivers/gpu/drm/radeon/radeon_object.c | 9 --------- 2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index f38fbcc..dfee7bb 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -53,6 +53,7 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size, struct drm_gem_object **obj) { struct radeon_bo *robj; + unsigned long max_size; int r;
*obj = NULL; @@ -60,6 +61,15 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size, if (alignment < PAGE_SIZE) { alignment = PAGE_SIZE; } + + /* maximun bo size is the minimun btw visible vram and gtt size */ + max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size); + if (size > max_size) { + printk(KERN_WARNING "%s:%d alloc size %dMb bigger than %ldMb limit\n", + __func__, __LINE__, size >> 20, max_size >> 20); + return -ENOMEM; + } + r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, NULL, &robj); if (r) { if (r != -ERESTARTSYS) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 8b27dd6..f404944 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -105,7 +105,6 @@ int radeon_bo_create(struct radeon_device *rdev, struct radeon_bo *bo; enum ttm_bo_type type; unsigned long page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT; - unsigned long max_size = 0; size_t acc_size; int r;
@@ -121,14 +120,6 @@ int radeon_bo_create(struct radeon_device *rdev, } *bo_ptr = NULL;
- /* maximun bo size is the minimun btw visible vram and gtt size */ - max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size); - if ((page_align << PAGE_SHIFT) >= max_size) { - printk(KERN_WARNING "%s:%d alloc size %ldM bigger than %ldMb limit\n", - __func__, __LINE__, page_align >> (20 - PAGE_SHIFT), max_size >> 20); - return -ENOMEM; - } - acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size, sizeof(struct radeon_bo));
When internal users want VRAM we shouldn't return GART memory instead.
Signed-off-by: Christian König deathsimple@vodafone.de Reviewed-by: Michel Dänzer michel.daenzer@amd.com --- drivers/gpu/drm/radeon/radeon_gem.c | 8 +++++++- drivers/gpu/drm/radeon/radeon_object.c | 10 ---------- 2 files changed, 7 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index dfee7bb..fe5c1f6 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -70,11 +70,17 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size, return -ENOMEM; }
+retry: r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, NULL, &robj); if (r) { - if (r != -ERESTARTSYS) + if (r != -ERESTARTSYS) { + if (initial_domain == RADEON_GEM_DOMAIN_VRAM) { + initial_domain |= RADEON_GEM_DOMAIN_GTT; + goto retry; + } DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n", size, initial_domain, alignment, r); + } return r; } *obj = &robj->gem_base; diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index f404944..b91118c 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -123,7 +123,6 @@ int radeon_bo_create(struct radeon_device *rdev, acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size, sizeof(struct radeon_bo));
-retry: bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); if (bo == NULL) return -ENOMEM; @@ -145,15 +144,6 @@ retry: acc_size, sg, &radeon_ttm_bo_destroy); up_read(&rdev->pm.mclk_lock); if (unlikely(r != 0)) { - if (r != -ERESTARTSYS) { - if (domain == RADEON_GEM_DOMAIN_VRAM) { - domain |= RADEON_GEM_DOMAIN_GTT; - goto retry; - } - dev_err(rdev->dev, - "object_init failed for (%lu, 0x%08X)\n", - size, domain); - } return r; } *bo_ptr = bo;
On Die, 2012-10-23 at 15:53 +0200, Christian König wrote:
GART and VRAM size limits need to be a power of two. Fix values greater than 1GB and simplify those checks a bit.
v2: also fix radeon_vram_limit usage, and simplify test even more.
Signed-off-by: Christian König deathsimple@vodafone.de
Reviewed-by: Michel Dänzer michel.daenzer@amd.com
dri-devel@lists.freedesktop.org