diff options
author | Michel Dänzer <[email protected]> | 2015-05-21 10:49:05 +0900 |
---|---|---|
committer | Michel Dänzer <[email protected]> | 2015-06-24 15:11:55 +0900 |
commit | 7796e8889a9a2cc1b454dc32d8da3d756404339a (patch) | |
tree | 652d14eda2f6c464f412f51cb37ed45015a6b079 | |
parent | 3fd4c80b32e3080d761e176d129a1e46c618584a (diff) |
winsys/radeon: Unmap GPU VM address range when destroying BO
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" <[email protected]>
Reviewed-by: Christian König <[email protected]>
-rw-r--r-- | src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 28 | ||||
-rw-r--r-- | src/gallium/winsys/radeon/drm/radeon_drm_winsys.c | 4 | ||||
-rw-r--r-- | src/gallium/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; |