summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2014-03-13 01:25:10 (GMT)
committerMichel Dänzer <michel@daenzer.net>2014-03-17 02:53:59 (GMT)
commit7e0396dd7330475ef72d8062d6d670c67f16d67b (patch)
treee1165c1d29e66f05b8c703a868a9acce93613594
parent361902ec04ee54a51f73cd6129d59a6fd7160097 (diff)
winsys/radeon: Store GPU virtual memory addresses of BOs in a hash table
This allows retrieving the existing BO and incrementing its reference count, instead of creating a separate winsys representation for it, when the kernel reports that the BO was already assigned a virtual memory address. This fixes problems with XWayland using radeonsi and the xf86-video-wlglamor driver, which calls GEM flink outside of the radeon winsys code and creates BOs from the flinked names using the same DRM file descriptor. Reviewed-by: Marek Olšák <marek.olsak@amd.com>
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_bo.c74
1 files changed, 26 insertions, 48 deletions
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
index 2ac060b..7dd5e7f 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
@@ -120,6 +120,8 @@ struct radeon_bomgr {
struct util_hash_table *bo_names;
/* List of buffer handles. Protectded by bo_handles_mutex. */
struct util_hash_table *bo_handles;
+ /* List of buffer virtual memory ranges. Protectded by bo_handles_mutex. */
+ struct util_hash_table *bo_vas;
pipe_mutex bo_handles_mutex;
pipe_mutex bo_va_mutex;
@@ -260,48 +262,6 @@ static uint64_t radeon_bomgr_find_va(struct radeon_bomgr *mgr, uint64_t size, ui
return offset;
}
-static void radeon_bomgr_force_va(struct radeon_bomgr *mgr, uint64_t va, uint64_t size)
-{
- size = align(size, 4096);
-
- pipe_mutex_lock(mgr->bo_va_mutex);
- if (va >= mgr->va_offset) {
- if (va > mgr->va_offset) {
- struct radeon_bo_va_hole *hole;
- hole = CALLOC_STRUCT(radeon_bo_va_hole);
- if (hole) {
- hole->size = va - mgr->va_offset;
- hole->offset = mgr->va_offset;
- list_add(&hole->list, &mgr->va_holes);
- }
- }
- mgr->va_offset = va + size;
- } else {
- struct radeon_bo_va_hole *hole, *n;
- uint64_t hole_end, va_end;
-
- /* Prune/free all holes that fall into the range
- */
- LIST_FOR_EACH_ENTRY_SAFE(hole, n, &mgr->va_holes, list) {
- hole_end = hole->offset + hole->size;
- va_end = va + size;
- if (hole->offset >= va_end || hole_end <= va)
- continue;
- if (hole->offset >= va && hole_end <= va_end) {
- list_del(&hole->list);
- FREE(hole);
- continue;
- }
- if (hole->offset >= va)
- hole->offset = va_end;
- else
- hole_end = va;
- hole->size = hole_end - hole->offset;
- }
- }
- pipe_mutex_unlock(mgr->bo_va_mutex);
-}
-
static void radeon_bomgr_free_va(struct radeon_bomgr *mgr, uint64_t va, uint64_t size)
{
struct radeon_bo_va_hole *hole;
@@ -625,11 +585,19 @@ static struct pb_buffer *radeon_bomgr_create_bo(struct pb_manager *_mgr,
radeon_bo_destroy(&bo->base);
return NULL;
}
+ pipe_mutex_lock(mgr->bo_handles_mutex);
if (va.operation == RADEON_VA_RESULT_VA_EXIST) {
- radeon_bomgr_free_va(mgr, bo->va, size);
- bo->va = va.offset;
- radeon_bomgr_force_va(mgr, bo->va, size);
+ struct pb_buffer *b = &bo->base;
+ struct radeon_bo *old_bo =
+ util_hash_table_get(mgr->bo_vas, (void*)(uintptr_t)va.offset);
+
+ pipe_mutex_unlock(mgr->bo_handles_mutex);
+ pb_reference(&b, &old_bo->base);
+ return b;
}
+
+ util_hash_table_set(mgr->bo_vas, (void*)(uintptr_t)bo->va, bo);
+ pipe_mutex_unlock(mgr->bo_handles_mutex);
}
if (rdesc->initial_domains & RADEON_DOMAIN_VRAM)
@@ -667,6 +635,7 @@ static void radeon_bomgr_destroy(struct pb_manager *_mgr)
struct radeon_bomgr *mgr = radeon_bomgr(_mgr);
util_hash_table_destroy(mgr->bo_names);
util_hash_table_destroy(mgr->bo_handles);
+ util_hash_table_destroy(mgr->bo_vas);
pipe_mutex_destroy(mgr->bo_handles_mutex);
pipe_mutex_destroy(mgr->bo_va_mutex);
FREE(mgr);
@@ -700,6 +669,7 @@ struct pb_manager *radeon_bomgr_create(struct radeon_drm_winsys *rws)
mgr->rws = rws;
mgr->bo_names = util_hash_table_create(handle_hash, handle_compare);
mgr->bo_handles = util_hash_table_create(handle_hash, handle_compare);
+ mgr->bo_vas = util_hash_table_create(handle_hash, handle_compare);
pipe_mutex_init(mgr->bo_handles_mutex);
pipe_mutex_init(mgr->bo_va_mutex);
@@ -999,11 +969,19 @@ done:
radeon_bo_destroy(&bo->base);
return NULL;
}
+ pipe_mutex_lock(mgr->bo_handles_mutex);
if (va.operation == RADEON_VA_RESULT_VA_EXIST) {
- radeon_bomgr_free_va(mgr, bo->va, bo->base.size);
- bo->va = va.offset;
- radeon_bomgr_force_va(mgr, bo->va, bo->base.size);
+ struct pb_buffer *b = &bo->base;
+ struct radeon_bo *old_bo =
+ util_hash_table_get(mgr->bo_vas, (void*)(uintptr_t)va.offset);
+
+ pipe_mutex_unlock(mgr->bo_handles_mutex);
+ pb_reference(&b, &old_bo->base);
+ return b;
}
+
+ util_hash_table_set(mgr->bo_vas, (void*)(uintptr_t)bo->va, bo);
+ pipe_mutex_unlock(mgr->bo_handles_mutex);
}
memset(&args, 0, sizeof(args));