Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 14dba717 authored by Thomas Hellstrom's avatar Thomas Hellstrom
Browse files

drm/vmwgfx: Reorganize the fence wait loop



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: default avatarThomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: default avatarBrian Paul <brianp@vmware.com>
Reviewed-by: default avatarDeepak Rawat <drawat@vmware.com>
parent 3fbeccf8
Loading
Loading
Loading
Loading
+26 −12
Original line number Diff line number Diff line
@@ -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);