diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 42 | ||||
-rw-r--r-- | src/gallium/winsys/radeon/drm/radeon_drm_winsys.c | 28 | ||||
-rw-r--r-- | src/gallium/winsys/radeon/drm/radeon_drm_winsys.h | 2 |
3 files changed, 64 insertions, 8 deletions
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c index bbfe5cc7884..06842a4fbc8 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c @@ -249,6 +249,12 @@ static uint64_t radeon_bomgr_find_va(const struct radeon_info *info, offset = heap->start; waste = offset % alignment; waste = waste ? alignment - waste : 0; + + if (offset + waste + size > heap->end) { + mtx_unlock(&heap->mutex); + return 0; + } + if (waste) { n = CALLOC_STRUCT(radeon_bo_va_hole); n->size = waste; @@ -261,6 +267,22 @@ static uint64_t radeon_bomgr_find_va(const struct radeon_info *info, return offset; } +static uint64_t radeon_bomgr_find_va64(struct radeon_drm_winsys *ws, + uint64_t size, uint64_t alignment) +{ + uint64_t va = 0; + + /* Try to allocate from the 64-bit address space first. + * If it doesn't exist (start = 0) or if it doesn't have enough space, + * fall back to the 32-bit address space. + */ + if (ws->vm64.start) + va = radeon_bomgr_find_va(&ws->info, &ws->vm64, size, alignment); + if (!va) + va = radeon_bomgr_find_va(&ws->info, &ws->vm32, size, alignment); + return va; +} + static void radeon_bomgr_free_va(const struct radeon_info *info, struct radeon_vm_heap *heap, uint64_t va, uint64_t size) @@ -370,7 +392,9 @@ void radeon_bo_destroy(struct pb_buffer *_buf) } } - radeon_bomgr_free_va(&rws->info, &rws->vm64, bo->va, bo->base.size); + radeon_bomgr_free_va(&rws->info, + bo->va < rws->vm32.end ? &rws->vm32 : &rws->vm64, + bo->va, bo->base.size); } /* Close object. */ @@ -660,8 +684,14 @@ static struct radeon_bo *radeon_create_bo(struct radeon_drm_winsys *rws, unsigned va_gap_size; va_gap_size = rws->check_vm ? MAX2(4 * alignment, 64 * 1024) : 0; - bo->va = radeon_bomgr_find_va(&rws->info, &rws->vm64, - size + va_gap_size, alignment); + + if (flags & RADEON_FLAG_32BIT) { + bo->va = radeon_bomgr_find_va(&rws->info, &rws->vm32, + size + va_gap_size, alignment); + assert(bo->va + size < rws->vm32.end); + } else { + bo->va = radeon_bomgr_find_va64(rws, size + va_gap_size, alignment); + } va.handle = bo->handle; va.vm_id = 0; @@ -1062,8 +1092,7 @@ static struct pb_buffer *radeon_winsys_bo_from_ptr(struct radeon_winsys *rws, if (ws->info.has_virtual_memory) { struct drm_radeon_gem_va va; - bo->va = radeon_bomgr_find_va(&ws->info, &ws->vm64, - bo->base.size, 1 << 20); + bo->va = radeon_bomgr_find_va64(ws, bo->base.size, 1 << 20); va.handle = bo->handle; va.operation = RADEON_VA_MAP; @@ -1206,8 +1235,7 @@ done: if (ws->info.has_virtual_memory && !bo->va) { struct drm_radeon_gem_va va; - bo->va = radeon_bomgr_find_va(&ws->info, &ws->vm64, - bo->base.size, 1 << 20); + bo->va = radeon_bomgr_find_va64(ws, bo->base.size, 1 << 20); va.handle = bo->handle; va.operation = RADEON_VA_MAP; diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c index 4fe36dc3f25..85a186af978 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c @@ -363,6 +363,8 @@ static bool do_winsys_init(struct radeon_drm_winsys *ws) ws->info.max_alloc_size = MIN2(ws->info.vram_size * 0.7, ws->info.max_alloc_size); if (ws->info.drm_minor < 40) ws->info.max_alloc_size = MIN2(ws->info.max_alloc_size, 256*1024*1024); + /* Both 32-bit and 64-bit address spaces only have 4GB. */ + ws->info.max_alloc_size = MIN2(ws->info.max_alloc_size, 3ull*1024*1024*1024); /* Get max clock frequency info and convert it to MHz */ radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_SCLK, NULL, @@ -553,6 +555,7 @@ static void radeon_winsys_destroy(struct radeon_winsys *rws) util_hash_table_destroy(ws->bo_handles); util_hash_table_destroy(ws->bo_vas); mtx_destroy(&ws->bo_handles_mutex); + mtx_destroy(&ws->vm32.mutex); mtx_destroy(&ws->vm64.mutex); mtx_destroy(&ws->bo_fence_lock); @@ -816,11 +819,34 @@ radeon_drm_winsys_create(int fd, const struct pipe_screen_config *config, ws->bo_handles = util_hash_table_create(handle_hash, handle_compare); ws->bo_vas = util_hash_table_create(handle_hash, handle_compare); (void) mtx_init(&ws->bo_handles_mutex, mtx_plain); + (void) mtx_init(&ws->vm32.mutex, mtx_plain); (void) mtx_init(&ws->vm64.mutex, mtx_plain); (void) mtx_init(&ws->bo_fence_lock, mtx_plain); + list_inithead(&ws->vm32.holes); list_inithead(&ws->vm64.holes); - ws->vm64.start = ws->va_start; + /* The kernel currently returns 8MB. Make sure this doesn't change. */ + if (ws->va_start > 8 * 1024 * 1024) { + /* Not enough 32-bit address space. */ + radeon_winsys_destroy(&ws->base); + mtx_unlock(&fd_tab_mutex); + return NULL; + } + + ws->vm32.start = ws->va_start; + ws->vm32.end = 1ull << 32; + + /* The maximum is 8GB of virtual address space limited by the kernel. + * It's obviously not enough for bigger cards, like Hawaiis with 4GB + * and 8GB of physical memory and 4GB of GART. + * + * Older kernels set the limit to 4GB, which is even worse, so they only + * have 32-bit address space. + */ + if (ws->info.drm_minor >= 41) { + ws->vm64.start = 1ull << 32; + ws->vm64.end = 1ull << 33; + } /* TTM aligns the BO size to the CPU page size */ ws->info.gart_page_size = sysconf(_SC_PAGESIZE); diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h index c65f5cb7108..03d96ea4c10 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h @@ -48,6 +48,7 @@ enum radeon_generation { struct radeon_vm_heap { mtx_t mutex; uint64_t start; + uint64_t end; struct list_head holes; }; @@ -84,6 +85,7 @@ struct radeon_drm_winsys { mtx_t bo_handles_mutex; mtx_t bo_fence_lock; + struct radeon_vm_heap vm32; struct radeon_vm_heap vm64; bool check_vm; |