From 7796e8889a9a2cc1b454dc32d8da3d756404339a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michel=20D=C3=A4nzer?= Date: Thu, 21 May 2015 10:49:05 +0900 Subject: [PATCH] winsys/radeon: Unmap GPU VM address range when destroying BO MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit But only when doing so is safe according to the RADEON_INFO_VA_UNMAP_WORKING kernel query. This avoids kernel GPU VM address range conflicts when the BO has other references than the GEM handle being closed, e.g. when the BO is shared. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90537 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90873 Cc: "10.5 10.6" Reviewed-by: Christian König --- src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 28 ++++++++++++++++--- .../winsys/radeon/drm/radeon_drm_winsys.c | 4 +++ .../winsys/radeon/drm/radeon_drm_winsys.h | 1 + 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c index fe98870967a..78c95b15eb2 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c @@ -305,14 +305,34 @@ static void radeon_bo_destroy(struct pb_buffer *_buf) if (bo->ptr) os_munmap(bo->ptr, bo->base.size); + if (mgr->va) { + if (bo->rws->va_unmap_working) { + struct drm_radeon_gem_va va; + + va.handle = bo->handle; + va.vm_id = 0; + va.operation = RADEON_VA_UNMAP; + va.flags = RADEON_VM_PAGE_READABLE | + RADEON_VM_PAGE_WRITEABLE | + RADEON_VM_PAGE_SNOOPED; + va.offset = bo->va; + + if (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_VA, &va, + sizeof(va)) != 0 && + va.operation == RADEON_VA_RESULT_ERROR) { + fprintf(stderr, "radeon: Failed to deallocate virtual address for buffer:\n"); + fprintf(stderr, "radeon: size : %d bytes\n", bo->base.size); + fprintf(stderr, "radeon: va : 0x%016llx\n", (unsigned long long)bo->va); + } + } + + radeon_bomgr_free_va(mgr, bo->va, bo->base.size); + } + /* Close object. */ args.handle = bo->handle; drmIoctl(bo->rws->fd, DRM_IOCTL_GEM_CLOSE, &args); - if (mgr->va) { - radeon_bomgr_free_va(mgr, bo->va, bo->base.size); - } - pipe_mutex_destroy(bo->map_mutex); if (bo->initial_domain & RADEON_DOMAIN_VRAM) diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c index ba8d1437b6f..d457f8a5ad1 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c @@ -57,6 +57,8 @@ #define RADEON_INFO_READ_REG 0x24 #endif +#define RADEON_INFO_VA_UNMAP_WORKING 0x25 + static struct util_hash_table *fd_tab = NULL; pipe_static_mutex(fd_tab_mutex); @@ -399,6 +401,8 @@ static boolean do_winsys_init(struct radeon_drm_winsys *ws) if (!radeon_get_drm_value(ws->fd, RADEON_INFO_IB_VM_MAX_SIZE, NULL, &ib_vm_max_size)) ws->info.r600_virtual_address = FALSE; + radeon_get_drm_value(ws->fd, RADEON_INFO_VA_UNMAP_WORKING, NULL, + &ws->va_unmap_working); } if (ws->gen == DRV_R600 && !debug_get_bool_option("RADEON_VA", FALSE)) ws->info.r600_virtual_address = FALSE; diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h index 166b6b93d28..99c8b8a8a1d 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h @@ -74,6 +74,7 @@ struct radeon_drm_winsys { enum radeon_generation gen; struct radeon_info info; uint32_t va_start; + uint32_t va_unmap_working; uint32_t accel_working2; struct pb_manager *kman; -- 2.30.2