From 2d3301e4d513614873002707d32453f926f63666 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 29 Jan 2016 16:36:29 -0600 Subject: [PATCH] virgl: fix reference counting of prime handles The virgl reference counting of buffers is broken for prime fd buffers. Each prime fd passed into virgl_drm_winsys_resource_create_handle creates a new resource. The solution requires creating a separate hash table to track flink names separately from prime handles. Signed-off-by: Rob Herring Signed-off-by: Dave Airlie --- .../winsys/virgl/drm/virgl_drm_winsys.c | 44 ++++++++++++++----- .../winsys/virgl/drm/virgl_drm_winsys.h | 1 + 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c index 48a79faa4bb..a49a89ebc99 100644 --- a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c +++ b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c @@ -53,10 +53,17 @@ static void virgl_hw_res_destroy(struct virgl_drm_winsys *qdws, { struct drm_gem_close args; - if (res->name) { + if (res->flinked) { + pipe_mutex_lock(qdws->bo_handles_mutex); + util_hash_table_remove(qdws->bo_names, + (void *)(uintptr_t)res->flink); + pipe_mutex_unlock(qdws->bo_handles_mutex); + } + + if (res->bo_handle) { pipe_mutex_lock(qdws->bo_handles_mutex); util_hash_table_remove(qdws->bo_handles, - (void *)(uintptr_t)res->name); + (void *)(uintptr_t)res->bo_handle); pipe_mutex_unlock(qdws->bo_handles_mutex); } @@ -112,6 +119,7 @@ virgl_drm_winsys_destroy(struct virgl_winsys *qws) virgl_cache_flush(qdws); util_hash_table_destroy(qdws->bo_handles); + util_hash_table_destroy(qdws->bo_names); pipe_mutex_destroy(qdws->bo_handles_mutex); pipe_mutex_destroy(qdws->mutex); @@ -370,11 +378,12 @@ virgl_drm_winsys_resource_create_handle(struct virgl_winsys *qws, struct drm_gem_open open_arg = {}; struct drm_virtgpu_resource_info info_arg = {}; struct virgl_hw_res *res; + uint32_t handle = whandle->handle; pipe_mutex_lock(qdws->bo_handles_mutex); if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { - res = util_hash_table_get(qdws->bo_handles, (void*)(uintptr_t)whandle->handle); + res = util_hash_table_get(qdws->bo_names, (void*)(uintptr_t)handle); if (res) { struct virgl_hw_res *r = NULL; virgl_drm_resource_reference(qdws, &r, res); @@ -382,21 +391,31 @@ virgl_drm_winsys_resource_create_handle(struct virgl_winsys *qws, } } - res = CALLOC_STRUCT(virgl_hw_res); - if (!res) - goto done; - if (whandle->type == DRM_API_HANDLE_TYPE_FD) { int r; - uint32_t handle; r = drmPrimeFDToHandle(qdws->fd, whandle->handle, &handle); if (r) { - FREE(res); res = NULL; goto done; } + } + + res = util_hash_table_get(qdws->bo_handles, (void*)(uintptr_t)handle); + fprintf(stderr, "resource %p for handle %d, pfd=%d\n", res, handle, whandle->handle); + if (res) { + struct virgl_hw_res *r = NULL; + virgl_drm_resource_reference(qdws, &r, res); + goto done; + } + + res = CALLOC_STRUCT(virgl_hw_res); + if (!res) + goto done; + + if (whandle->type == DRM_API_HANDLE_TYPE_FD) { res->bo_handle = handle; } else { + fprintf(stderr, "gem open handle %d\n", handle); memset(&open_arg, 0, sizeof(open_arg)); open_arg.name = whandle->handle; if (drmIoctl(qdws->fd, DRM_IOCTL_GEM_OPEN, &open_arg)) { @@ -406,7 +425,7 @@ virgl_drm_winsys_resource_create_handle(struct virgl_winsys *qws, } res->bo_handle = open_arg.handle; } - res->name = whandle->handle; + res->name = handle; memset(&info_arg, 0, sizeof(info_arg)); info_arg.bo_handle = res->bo_handle; @@ -425,7 +444,7 @@ virgl_drm_winsys_resource_create_handle(struct virgl_winsys *qws, pipe_reference_init(&res->reference, 1); res->num_cs_references = 0; - util_hash_table_set(qdws->bo_handles, (void *)(uintptr_t)whandle->handle, res); + util_hash_table_set(qdws->bo_handles, (void *)(uintptr_t)handle, res); done: pipe_mutex_unlock(qdws->bo_handles_mutex); @@ -455,7 +474,7 @@ static boolean virgl_drm_winsys_resource_get_handle(struct virgl_winsys *qws, res->flink = flink.name; pipe_mutex_lock(qdws->bo_handles_mutex); - util_hash_table_set(qdws->bo_handles, (void *)(uintptr_t)res->flink, res); + util_hash_table_set(qdws->bo_names, (void *)(uintptr_t)res->flink, res); pipe_mutex_unlock(qdws->bo_handles_mutex); } whandle->handle = res->flink; @@ -751,6 +770,7 @@ virgl_drm_winsys_create(int drmFD) pipe_mutex_init(qdws->mutex); pipe_mutex_init(qdws->bo_handles_mutex); qdws->bo_handles = util_hash_table_create(handle_hash, handle_compare); + qdws->bo_names = util_hash_table_create(handle_hash, handle_compare); qdws->base.destroy = virgl_drm_winsys_destroy; qdws->base.transfer_put = virgl_bo_transfer_put; diff --git a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h index da85ff87d2a..ffd7658ca81 100644 --- a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h +++ b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h @@ -62,6 +62,7 @@ struct virgl_drm_winsys pipe_mutex mutex; struct util_hash_table *bo_handles; + struct util_hash_table *bo_names; pipe_mutex bo_handles_mutex; }; -- 2.30.2