[Mesa-dev] [PATCH 1/2] winsys/radeon: fix VA allocation

Christian König deathsimple at vodafone.de
Fri Aug 3 08:06:01 PDT 2012


Wait for VA use to end before reusing it.

Should fix: https://bugs.freedesktop.org/show_bug.cgi?id=45018

Signed-off-by: Christian König <deathsimple at vodafone.de>
---
 src/gallium/winsys/radeon/drm/radeon_drm_bo.c |   64 +++++++++++++++++--------
 1 file changed, 43 insertions(+), 21 deletions(-)

diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
index 2626586..0c94461 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
@@ -102,6 +102,7 @@ static INLINE struct radeon_bo *radeon_bo(struct pb_buffer *bo)
 
 struct radeon_bo_va_hole {
     struct list_head list;
+    uint32_t         handle;
     uint64_t         offset;
     uint64_t         size;
 };
@@ -204,7 +205,30 @@ static uint64_t radeon_bomgr_find_va(struct radeon_bomgr *mgr, uint64_t size, ui
     pipe_mutex_lock(mgr->bo_va_mutex);
     /* first look for a hole */
     LIST_FOR_EACH_ENTRY_SAFE(hole, n, &mgr->va_holes, list) {
+        if (hole->handle) {
+            struct drm_radeon_gem_busy busy_args;
+            struct drm_gem_close close_args;
+
+            memset(&busy_args, 0, sizeof(busy_args));
+            busy_args.handle = hole->handle;
+            if (drmCommandWriteRead(mgr->rws->fd, DRM_RADEON_GEM_BUSY,
+                                    &busy_args, sizeof(busy_args)) != 0) {
+                continue;
+            }
+
+            memset(&close_args, 0, sizeof(close_args));
+            close_args.handle = hole->handle;
+            drmIoctl(mgr->rws->fd, DRM_IOCTL_GEM_CLOSE, &close_args);
+
+            hole->handle = 0;
+        }
         offset = hole->offset;
+	if ((offset + hole->size) == mgr->va_offset) {
+            mgr->va_offset = offset;
+            list_del(&hole->list);
+            FREE(hole);
+            continue;
+	}
         waste = 0;
         if (alignment) {
             waste = offset % alignment;
@@ -280,23 +304,21 @@ static void radeon_bomgr_force_va(struct radeon_bomgr *mgr, uint64_t va, uint64_
     pipe_mutex_unlock(mgr->bo_va_mutex);
 }
 
-static void radeon_bomgr_free_va(struct radeon_bomgr *mgr, uint64_t va, uint64_t size)
+static void radeon_bomgr_free_va(struct radeon_bomgr *mgr, uint64_t va,
+                                 uint64_t size, uint32_t handle)
 {
+    struct radeon_bo_va_hole *hole;
     pipe_mutex_lock(mgr->bo_va_mutex);
-    if ((va + size) == mgr->va_offset) {
-        mgr->va_offset = va;
-    } else {
-        struct radeon_bo_va_hole *hole;
 
-        /* FIXME on allocation failure we just lose virtual address space
-         * maybe print a warning
-         */
-        hole = CALLOC_STRUCT(radeon_bo_va_hole);
-        if (hole) {
-            hole->size = size;
-            hole->offset = va;
-            list_add(&hole->list, &mgr->va_holes);
-        }
+    /* FIXME on allocation failure we just lose virtual address space
+     * maybe print a warning
+     */
+    hole = CALLOC_STRUCT(radeon_bo_va_hole);
+    if (hole) {
+        hole->handle = handle;
+        hole->size = size;
+        hole->offset = va;
+        list_add(&hole->list, &mgr->va_holes);
     }
     pipe_mutex_unlock(mgr->bo_va_mutex);
 }
@@ -320,12 +342,12 @@ static void radeon_bo_destroy(struct pb_buffer *_buf)
         os_munmap(bo->ptr, bo->base.size);
 
     if (mgr->va) {
-        radeon_bomgr_free_va(mgr, bo->va, bo->va_size);
+        radeon_bomgr_free_va(mgr, bo->va, bo->va_size, bo->handle);
+    } else {
+        /* Close object. */
+        args.handle = bo->handle;
+        drmIoctl(bo->rws->fd, DRM_IOCTL_GEM_CLOSE, &args);
     }
-
-    /* Close object. */
-    args.handle = bo->handle;
-    drmIoctl(bo->rws->fd, DRM_IOCTL_GEM_CLOSE, &args);
     pipe_mutex_destroy(bo->map_mutex);
     FREE(bo);
 }
@@ -540,7 +562,7 @@ static struct pb_buffer *radeon_bomgr_create_bo(struct pb_manager *_mgr,
             return NULL;
         }
         if (va.operation == RADEON_VA_RESULT_VA_EXIST) {
-            radeon_bomgr_free_va(mgr, bo->va, bo->va_size);
+            radeon_bomgr_free_va(mgr, bo->va, bo->va_size, 0);
             bo->va = va.offset;
             radeon_bomgr_force_va(mgr, bo->va, bo->va_size);
         }
@@ -865,7 +887,7 @@ done:
             return NULL;
         }
         if (va.operation == RADEON_VA_RESULT_VA_EXIST) {
-            radeon_bomgr_free_va(mgr, bo->va, bo->va_size);
+            radeon_bomgr_free_va(mgr, bo->va, bo->va_size, 0);
             bo->va = va.offset;
             radeon_bomgr_force_va(mgr, bo->va, bo->va_size);
         }
-- 
1.7.9.5



More information about the mesa-dev mailing list