]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/vmwgfx: Reorganize the fence wait loop
authorThomas Hellstrom <thellstrom@vmware.com>
Wed, 20 Jun 2018 09:51:02 +0000 (11:51 +0200)
committerThomas Hellstrom <thellstrom@vmware.com>
Tue, 3 Jul 2018 18:40:48 +0000 (20:40 +0200)
Reorganize the fence wait loop somewhat to make it look more like the
examples in set_current_state() kerneldoc, and add some code comments.

Also if we're about to time out, make sure we check again whether the fence
is actually signaled.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Deepak Rawat <drawat@vmware.com>
drivers/gpu/drm/vmwgfx/vmwgfx_fence.c

index 9ed544f8958f322b8fc4f34835e10414921a211d..ea41d74d83419580854cbf906e09b38f972eec24 100644 (file)
@@ -175,7 +175,6 @@ static long vmw_fence_wait(struct dma_fence *f, bool intr, signed long timeout)
        struct vmw_private *dev_priv = fman->dev_priv;
        struct vmwgfx_wait_cb cb;
        long ret = timeout;
-       unsigned long irq_flags;
 
        if (likely(vmw_fence_obj_signaled(fence)))
                return timeout;
@@ -183,7 +182,7 @@ static long vmw_fence_wait(struct dma_fence *f, bool intr, signed long timeout)
        vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
        vmw_seqno_waiter_add(dev_priv);
 
-       spin_lock_irqsave(f->lock, irq_flags);
+       spin_lock(f->lock);
 
        if (intr && signal_pending(current)) {
                ret = -ERESTARTSYS;
@@ -194,30 +193,45 @@ static long vmw_fence_wait(struct dma_fence *f, bool intr, signed long timeout)
        cb.task = current;
        list_add(&cb.base.node, &f->cb_list);
 
-       while (ret > 0) {
+       for (;;) {
                __vmw_fences_update(fman);
-               if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &f->flags))
-                       break;
 
+               /*
+                * We can use the barrier free __set_current_state() since
+                * DMA_FENCE_FLAG_SIGNALED_BIT + wakeup is protected by the
+                * fence spinlock.
+                */
                if (intr)
                        __set_current_state(TASK_INTERRUPTIBLE);
                else
                        __set_current_state(TASK_UNINTERRUPTIBLE);
-               spin_unlock_irqrestore(f->lock, irq_flags);
 
-               ret = schedule_timeout(ret);
+               if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &f->flags)) {
+                       if (ret == 0 && timeout > 0)
+                               ret = 1;
+                       break;
+               }
 
-               spin_lock_irqsave(f->lock, irq_flags);
-               if (ret > 0 && intr && signal_pending(current))
+               if (intr && signal_pending(current)) {
                        ret = -ERESTARTSYS;
-       }
+                       break;
+               }
 
+               if (ret == 0)
+                       break;
+
+               spin_unlock(f->lock);
+
+               ret = schedule_timeout(ret);
+
+               spin_lock(f->lock);
+       }
+       __set_current_state(TASK_RUNNING);
        if (!list_empty(&cb.base.node))
                list_del(&cb.base.node);
-       __set_current_state(TASK_RUNNING);
 
 out:
-       spin_unlock_irqrestore(f->lock, irq_flags);
+       spin_unlock(f->lock);
 
        vmw_seqno_waiter_remove(dev_priv);