r600g: add bo busy backoff.
authorDave Airlie <airlied@redhat.com>
Tue, 5 Oct 2010 05:51:38 +0000 (15:51 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 5 Oct 2010 05:51:38 +0000 (15:51 +1000)
When we go to do a lot of bos in one draw like constant bufs we need
to avoid bouncing off the busy ioctl, this mitigates by backing off
on busy bos for a short amount of times.

src/gallium/winsys/r600/drm/r600_priv.h
src/gallium/winsys/r600/drm/radeon_bo.c

index 76a7ba9ec25b5c07d00f993594403f0f4d6dea88..285a192e743f271e758ff03f0b1720d6e4a8fe3d 100644 (file)
@@ -66,6 +66,8 @@ struct radeon_bo {
        void                            *data;
        struct list_head                fencedlist;
        boolean                         shared;
+       int64_t                         last_busy;
+       boolean                         set_busy;
 };
 
 struct r600_bo {
index 97138f9f9ef5ac84c3dd8e941909455b06c9e954..42a23f0ab8f727c2f8389595b4adb9082b33a6ce 100644 (file)
@@ -32,6 +32,7 @@
 #include "r600_priv.h"
 #include "xf86drm.h"
 #include "radeon_drm.h"
+#include "util/u_time.h"
 
 static int radeon_bo_fixed_map(struct radeon *radeon, struct radeon_bo *bo)
 {
@@ -170,14 +171,23 @@ int radeon_bo_wait(struct radeon *radeon, struct radeon_bo *bo)
        return ret;
 }
 
+#define BO_BUSY_BACKOFF 10000
+
 int radeon_bo_busy(struct radeon *radeon, struct radeon_bo *bo, uint32_t *domain)
 {
        struct drm_radeon_gem_busy args;
        int ret;
+       int64_t now;
 
+       now = os_time_get();
        if (LIST_IS_EMPTY(&bo->fencedlist) && !bo->shared)
                return 0;
 
+       if (bo->set_busy && (now - bo->last_busy < BO_BUSY_BACKOFF))
+               return -EBUSY;
+
+       bo->set_busy = FALSE;
+
        memset(&args, 0, sizeof(args));
        args.handle = bo->handle;
        args.domain = 0;
@@ -190,6 +200,9 @@ int radeon_bo_busy(struct radeon *radeon, struct radeon_bo *bo, uint32_t *domain
                LIST_FOR_EACH_ENTRY_SAFE(entry, tent, &bo->fencedlist, fencedlist) {
                        LIST_DELINIT(&entry->fencedlist);
                }
+       } else {
+               bo->set_busy = TRUE;
+               bo->last_busy = now;
        }
        *domain = args.domain;
        return ret;