]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/nouveau/nouveau_fence.c
drm/nouveau: Use lazy fence waits when doing software interchannel sync.
[karo-tx-linux.git] / drivers / gpu / drm / nouveau / nouveau_fence.c
index 441b12420bb1b713fb56b98edad389d31fe367ea..0a22955998e81a36b273556cf5223c083fd98b51 100644 (file)
@@ -249,6 +249,7 @@ alloc_semaphore(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_semaphore *sema;
+       int ret;
 
        if (!USE_SEMA(dev))
                return NULL;
@@ -257,10 +258,14 @@ alloc_semaphore(struct drm_device *dev)
        if (!sema)
                goto fail;
 
+       ret = drm_mm_pre_get(&dev_priv->fence.heap);
+       if (ret)
+               goto fail;
+
        spin_lock(&dev_priv->fence.lock);
        sema->mem = drm_mm_search_free(&dev_priv->fence.heap, 4, 0, 0);
        if (sema->mem)
-               sema->mem = drm_mm_get_block(sema->mem, 4, 0);
+               sema->mem = drm_mm_get_block_atomic(sema->mem, 4, 0);
        spin_unlock(&dev_priv->fence.lock);
 
        if (!sema->mem)
@@ -385,7 +390,16 @@ nouveau_fence_sync(struct nouveau_fence *fence,
        if (!sema) {
                /* Early card or broken userspace, fall back to
                 * software sync. */
-               return nouveau_fence_wait(fence, NULL, false, false);
+               return nouveau_fence_wait(fence, NULL, true, false);
+       }
+
+       /* try to take chan's mutex, if we can't take it right away
+        * we have to fallback to software sync to prevent locking
+        * order issues
+        */
+       if (!mutex_trylock(&chan->mutex)) {
+               free_semaphore(&sema->ref);
+               return nouveau_fence_wait(fence, NULL, true, false);
        }
 
        /* Make wchan wait until it gets signalled */
@@ -395,6 +409,7 @@ nouveau_fence_sync(struct nouveau_fence *fence,
 
        /* Signal the semaphore from chan */
        ret = emit_semaphore(chan, NV_SW_SEMAPHORE_RELEASE, sema);
+       mutex_unlock(&chan->mutex);
 out:
        kref_put(&sema->ref, free_semaphore);
        return ret;