Module Name:    src
Committed By:   riastradh
Date:           Tue Oct 25 23:34:06 UTC 2022

Modified Files:
        src/sys/external/bsd/drm2/dist/drm/vmwgfx: vmwgfx_drv.c vmwgfx_drv.h
            vmwgfx_execbuf.c vmwgfx_fence.c vmwgfx_fifo.c vmwgfx_irq.c

Log Message:
vmwgfx(4): Convert fence_queue and fifo_queue to drm_waitqueue_t.


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 \
    src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_drv.c
cvs rdiff -u -r1.6 -r1.7 \
    src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_drv.h
cvs rdiff -u -r1.3 -r1.4 \
    src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_execbuf.c \
    src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_fence.c \
    src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_fifo.c \
    src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_irq.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_drv.c
diff -u src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_drv.c:1.5 src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_drv.c:1.6
--- src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_drv.c:1.5	Thu Feb 17 01:21:02 2022
+++ src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_drv.c	Tue Oct 25 23:34:05 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: vmwgfx_drv.c,v 1.5 2022/02/17 01:21:02 riastradh Exp $	*/
+/*	$NetBSD: vmwgfx_drv.c,v 1.6 2022/10/25 23:34:05 riastradh Exp $	*/
 
 // SPDX-License-Identifier: GPL-2.0 OR MIT
 /**************************************************************************
@@ -28,7 +28,7 @@
  **************************************************************************/
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vmwgfx_drv.c,v 1.5 2022/02/17 01:21:02 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vmwgfx_drv.c,v 1.6 2022/10/25 23:34:05 riastradh Exp $");
 
 #include <linux/console.h>
 #include <linux/dma-mapping.h>
@@ -655,8 +655,10 @@ static int vmw_driver_load(struct drm_de
 		INIT_LIST_HEAD(&dev_priv->res_lru[i]);
 	}
 
-	init_waitqueue_head(&dev_priv->fence_queue);
-	init_waitqueue_head(&dev_priv->fifo_queue);
+	DRM_INIT_WAITQUEUE(&dev_priv->fence_queue, "vmwgfence");
+	spin_lock_init(&dev_priv->fence_lock);
+	DRM_INIT_WAITQUEUE(&dev_priv->fifo_queue, "vmwgfifo");
+	spin_lock_init(&dev_priv->fifo_lock);
 	dev_priv->fence_queue_waiters = 0;
 	dev_priv->fifo_queue_waiters = 0;
 
@@ -963,6 +965,11 @@ out_no_device:
 out_err4:
 	memunmap(dev_priv->mmio_virt);
 out_err0:
+	spin_lock_destroy(&dev_priv->fifo_lock);
+	DRM_DESTROY_WAITQUEUE(&dev_priv->fifo_queue);
+	spin_lock_destroy(&dev_priv->fence_lock);
+	DRM_DESTROY_WAITQUEUE(&dev_priv->fence_queue);
+
 	for (i = vmw_res_context; i < vmw_res_max; ++i)
 		idr_destroy(&dev_priv->res_idr[i]);
 
@@ -1015,6 +1022,11 @@ static void vmw_driver_unload(struct drm
 	if (dev_priv->ctx.staged_bindings)
 		vmw_binding_state_free(dev_priv->ctx.staged_bindings);
 
+	spin_lock_destroy(&dev_priv->fifo_lock);
+	DRM_DESTROY_WAITQUEUE(&dev_priv->fifo_queue);
+	spin_lock_destroy(&dev_priv->fence_lock);
+	DRM_DESTROY_WAITQUEUE(&dev_priv->fence_queue);
+
 	for (i = vmw_res_context; i < vmw_res_max; ++i)
 		idr_destroy(&dev_priv->res_idr[i]);
 

Index: src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_drv.h
diff -u src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_drv.h:1.6 src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_drv.h:1.7
--- src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_drv.h:1.6	Thu Feb 17 01:21:02 2022
+++ src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_drv.h	Tue Oct 25 23:34:05 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: vmwgfx_drv.h,v 1.6 2022/02/17 01:21:02 riastradh Exp $	*/
+/*	$NetBSD: vmwgfx_drv.h,v 1.7 2022/10/25 23:34:05 riastradh Exp $	*/
 
 /* SPDX-License-Identifier: GPL-2.0 OR MIT */
 /**************************************************************************
@@ -538,7 +538,9 @@ struct vmw_private {
 
 	atomic_t marker_seq;
 	drm_waitqueue_t fence_queue;
+	spinlock_t fence_lock;
 	drm_waitqueue_t fifo_queue;
+	spinlock_t fifo_lock;
 	spinlock_t waiter_lock;
 	int fence_queue_waiters; /* Protected by waiter_lock */
 	int goal_queue_waiters; /* Protected by waiter_lock */

Index: src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_execbuf.c
diff -u src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_execbuf.c:1.3 src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_execbuf.c:1.4
--- src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_execbuf.c:1.3	Sat Dec 18 23:45:45 2021
+++ src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_execbuf.c	Tue Oct 25 23:34:05 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: vmwgfx_execbuf.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $	*/
+/*	$NetBSD: vmwgfx_execbuf.c,v 1.4 2022/10/25 23:34:05 riastradh Exp $	*/
 
 // SPDX-License-Identifier: GPL-2.0 OR MIT
 /**************************************************************************
@@ -27,7 +27,7 @@
  *
  **************************************************************************/
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vmwgfx_execbuf.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vmwgfx_execbuf.c,v 1.4 2022/10/25 23:34:05 riastradh Exp $");
 
 #include <linux/sync_file.h>
 
@@ -3447,8 +3447,10 @@ vmw_execbuf_copy_fence_user(struct vmw_p
 
 		fence_rep.handle = fence_handle;
 		fence_rep.seqno = fence->base.seqno;
+		spin_lock(&dev_priv->fence_lock);
 		vmw_update_seqno(dev_priv, &dev_priv->fifo);
 		fence_rep.passed_seqno = dev_priv->last_read_seqno;
+		spin_unlock(&dev_priv->fence_lock);
 	}
 
 	/*
Index: src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_fence.c
diff -u src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_fence.c:1.3 src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_fence.c:1.4
--- src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_fence.c:1.3	Sat Dec 18 23:45:45 2021
+++ src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_fence.c	Tue Oct 25 23:34:05 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: vmwgfx_fence.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $	*/
+/*	$NetBSD: vmwgfx_fence.c,v 1.4 2022/10/25 23:34:05 riastradh Exp $	*/
 
 // SPDX-License-Identifier: GPL-2.0 OR MIT
 /**************************************************************************
@@ -28,12 +28,14 @@
  **************************************************************************/
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vmwgfx_fence.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vmwgfx_fence.c,v 1.4 2022/10/25 23:34:05 riastradh Exp $");
 
 #include <linux/sched/signal.h>
 
 #include "vmwgfx_drv.h"
 
+#include <linux/nbsd-namespace.h>
+
 #define VMW_FENCE_WRAP (1 << 31)
 
 struct vmw_fence_manager {
@@ -158,7 +160,11 @@ static bool vmw_fence_enable_signaling(s
 
 struct vmwgfx_wait_cb {
 	struct dma_fence_cb base;
+#ifdef __NetBSD__
+	drm_waitqueue_t wq;
+#else
 	struct task_struct *task;
+#endif
 };
 
 static void
@@ -167,7 +173,11 @@ vmwgfx_wait_cb(struct dma_fence *fence, 
 	struct vmwgfx_wait_cb *wait =
 		container_of(cb, struct vmwgfx_wait_cb, base);
 
+#ifdef __NetBSD__
+	DRM_SPIN_WAKEUP_ALL(&wait->wq, fence->lock);
+#else
 	wake_up_process(wait->task);
+#endif
 }
 
 static void __vmw_fences_update(struct vmw_fence_manager *fman);
@@ -198,10 +208,26 @@ static long vmw_fence_wait(struct dma_fe
 		goto out;
 	}
 
-	cb.base.func = vmwgfx_wait_cb;
+#ifdef __NetBSD__
+	DRM_INIT_WAITQUEUE(&cb.wq, "vmwgfxwf");
+#else
 	cb.task = current;
-	list_add(&cb.base.node, &f->cb_list);
+#endif
+	spin_unlock(f->lock);
+	ret = dma_fence_add_callback(f, &cb.base, vmwgfx_wait_cb);
+	spin_lock(f->lock);
+	if (ret)
+		goto out;
 
+#ifdef __NetBSD__
+#define	C	(__vmw_fences_update(fman), dma_fence_is_signaled_locked(f))
+	if (intr) {
+		DRM_SPIN_TIMED_WAIT_UNTIL(ret, &cb.wq, f->lock, timeout, C);
+	} else {
+		DRM_SPIN_TIMED_WAIT_NOINTR_UNTIL(ret, &cb.wq, f->lock, timeout,
+		    C);
+	}
+#else
 	for (;;) {
 		__vmw_fences_update(fman);
 
@@ -238,9 +264,16 @@ static long vmw_fence_wait(struct dma_fe
 	__set_current_state(TASK_RUNNING);
 	if (!list_empty(&cb.base.node))
 		list_del(&cb.base.node);
+#endif
+	spin_unlock(f->lock);
+	dma_fence_remove_callback(f, &cb.base);
+	spin_lock(f->lock);
 
 out:
 	spin_unlock(f->lock);
+#ifdef __NetBSD__
+	DRM_DESTROY_WAITQUEUE(&cb.wq);
+#endif
 
 	vmw_seqno_waiter_remove(dev_priv);
 
@@ -878,8 +911,11 @@ int vmw_fence_obj_signaled_ioctl(struct 
 	arg->signaled = vmw_fence_obj_signaled(fence);
 
 	arg->signaled_flags = arg->flags;
+	spin_lock(&dev_priv->fence_lock);
+	const u32 seqno = dev_priv->last_read_seqno;
+	spin_unlock(&dev_priv->fence_lock);
 	spin_lock(&fman->lock);
-	arg->passed_seqno = dev_priv->last_read_seqno;
+	arg->passed_seqno = seqno;
 	spin_unlock(&fman->lock);
 
 	ttm_base_object_unref(&base);
Index: src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_fifo.c
diff -u src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_fifo.c:1.3 src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_fifo.c:1.4
--- src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_fifo.c:1.3	Sat Dec 18 23:45:45 2021
+++ src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_fifo.c	Tue Oct 25 23:34:06 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: vmwgfx_fifo.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $	*/
+/*	$NetBSD: vmwgfx_fifo.c,v 1.4 2022/10/25 23:34:06 riastradh Exp $	*/
 
 // SPDX-License-Identifier: GPL-2.0 OR MIT
 /**************************************************************************
@@ -28,7 +28,7 @@
  **************************************************************************/
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vmwgfx_fifo.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vmwgfx_fifo.c,v 1.4 2022/10/25 23:34:06 riastradh Exp $");
 
 #include <linux/sched/signal.h>
 
@@ -36,6 +36,8 @@ __KERNEL_RCSID(0, "$NetBSD: vmwgfx_fifo.
 
 #include "vmwgfx_drv.h"
 
+#include <linux/nbsd-namespace.h>
+
 struct vmw_temp_set_context {
 	SVGA3dCmdHeader header;
 	SVGA3dCmdDXTempSetContext body;
@@ -227,14 +229,20 @@ static int vmw_fifo_wait_noirq(struct vm
 {
 	int ret = 0;
 	unsigned long end_jiffies = jiffies + timeout;
+#ifdef __NetBSD__
+	assert_spin_locked(&dev_priv->fifo_lock);
+#else
 	DEFINE_WAIT(__wait);
+#endif
 
 	DRM_INFO("Fifo wait noirq.\n");
 
 	for (;;) {
+#ifndef __NetBSD__
 		prepare_to_wait(&dev_priv->fifo_queue, &__wait,
 				(interruptible) ?
 				TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+#endif
 		if (!vmw_fifo_is_full(dev_priv, bytes))
 			break;
 		if (time_after_eq(jiffies, end_jiffies)) {
@@ -242,14 +250,40 @@ static int vmw_fifo_wait_noirq(struct vm
 			DRM_ERROR("SVGA device lockup.\n");
 			break;
 		}
+#ifdef __NetBSD__
+		if (interruptible) {
+			DRM_SPIN_TIMED_WAIT_UNTIL(ret, &dev_priv->fifo_queue,
+			    &dev_priv->fifo_lock, 1,
+			    !vmw_fifo_is_full(dev_priv, bytes));
+		} else {
+			DRM_SPIN_TIMED_WAIT_NOINTR_UNTIL(ret,
+			    &dev_priv->fifo_queue,
+			    &dev_priv->fifo_lock, 1,
+			    !vmw_fifo_is_full(dev_priv, bytes));
+		}
+		if (ret) {
+			if (ret > 0) /* success */
+				ret = 0;
+			break;
+		}
+		/*
+		 * ret=0 means the wait timed out after one tick, so
+		 * try again
+		 */
+#else
 		schedule_timeout(1);
 		if (interruptible && signal_pending(current)) {
 			ret = -ERESTARTSYS;
 			break;
 		}
+#endif
 	}
+#ifdef __NetBSD__
+	DRM_SPIN_WAKEUP_ALL(&dev_priv->fifo_queue, &dev_priv->fifo_lock);
+#else
 	finish_wait(&dev_priv->fifo_queue, &__wait);
 	wake_up_all(&dev_priv->fifo_queue);
+#endif
 	DRM_INFO("Fifo noirq exit.\n");
 	return ret;
 }
@@ -260,25 +294,32 @@ static int vmw_fifo_wait(struct vmw_priv
 {
 	long ret = 1L;
 
-	if (likely(!vmw_fifo_is_full(dev_priv, bytes)))
+	spin_lock(&dev_priv->fifo_lock);
+
+	if (likely(!vmw_fifo_is_full(dev_priv, bytes))) {
+		spin_unlock(&dev_priv->fifo_lock);
 		return 0;
+	}
 
 	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_FIFOFULL);
-	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
-		return vmw_fifo_wait_noirq(dev_priv, bytes,
+	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK)) {
+		ret = vmw_fifo_wait_noirq(dev_priv, bytes,
 					   interruptible, timeout);
+		spin_unlock(&dev_priv->fifo_lock);
+		return ret;
+	}
 
 	vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_FIFO_PROGRESS,
 			       &dev_priv->fifo_queue_waiters);
 
 	if (interruptible)
-		ret = wait_event_interruptible_timeout
-		    (dev_priv->fifo_queue,
-		     !vmw_fifo_is_full(dev_priv, bytes), timeout);
+		DRM_SPIN_TIMED_WAIT_UNTIL(ret, &dev_priv->fifo_queue,
+		    &dev_priv->fifo_lock, timeout,
+		    !vmw_fifo_is_full(dev_priv, bytes));
 	else
-		ret = wait_event_timeout
-		    (dev_priv->fifo_queue,
-		     !vmw_fifo_is_full(dev_priv, bytes), timeout);
+		DRM_SPIN_TIMED_WAIT_NOINTR_UNTIL(ret, &dev_priv->fifo_queue,
+		    &dev_priv->fifo_lock, timeout,
+		    !vmw_fifo_is_full(dev_priv, bytes));
 
 	if (unlikely(ret == 0))
 		ret = -EBUSY;
@@ -288,6 +329,8 @@ static int vmw_fifo_wait(struct vmw_priv
 	vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_FIFO_PROGRESS,
 				  &dev_priv->fifo_queue_waiters);
 
+	spin_unlock(&dev_priv->fifo_lock);
+
 	return ret;
 }
 
@@ -576,7 +619,9 @@ int vmw_fifo_send_fence(struct vmw_priva
 	cmd_fence->fence = *seqno;
 	vmw_fifo_commit_flush(dev_priv, bytes);
 	(void) vmw_marker_push(&fifo_state->marker_queue, *seqno);
+	spin_lock(&dev_priv->fence_lock);
 	vmw_update_seqno(dev_priv, fifo_state);
+	spin_unlock(&dev_priv->fence_lock);
 
 out_err:
 	return ret;
Index: src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_irq.c
diff -u src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_irq.c:1.3 src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_irq.c:1.4
--- src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_irq.c:1.3	Sat Dec 18 23:45:45 2021
+++ src/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_irq.c	Tue Oct 25 23:34:06 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: vmwgfx_irq.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $	*/
+/*	$NetBSD: vmwgfx_irq.c,v 1.4 2022/10/25 23:34:06 riastradh Exp $	*/
 
 // SPDX-License-Identifier: GPL-2.0 OR MIT
 /**************************************************************************
@@ -28,7 +28,7 @@
  **************************************************************************/
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vmwgfx_irq.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vmwgfx_irq.c,v 1.4 2022/10/25 23:34:06 riastradh Exp $");
 
 #include <linux/sched/signal.h>
 
@@ -55,8 +55,11 @@ static irqreturn_t vmw_thread_fn(int irq
 
 	if (test_and_clear_bit(VMW_IRQTHREAD_FENCE,
 			       dev_priv->irqthread_pending)) {
+		spin_lock(&dev_priv->fence_lock);
 		vmw_fences_update(dev_priv->fman);
-		wake_up_all(&dev_priv->fence_queue);
+		DRM_SPIN_WAKEUP_ALL(&dev_priv->fence_queue,
+		    &dev_priv->fence_lock);
+		spin_unlock(&dev_priv->fence_lock);
 		ret = IRQ_HANDLED;
 	}
 
@@ -96,8 +99,12 @@ static irqreturn_t vmw_irq_handler(int i
 	if (!status)
 		return IRQ_NONE;
 
-	if (masked_status & SVGA_IRQFLAG_FIFO_PROGRESS)
-		wake_up_all(&dev_priv->fifo_queue);
+	if (masked_status & SVGA_IRQFLAG_FIFO_PROGRESS) {
+		spin_lock(&dev_priv->fifo_lock);
+		DRM_SPIN_WAKEUP_ALL(&dev_priv->fifo_queue,
+		    &dev_priv->fifo_lock);
+		spin_unlock(&dev_priv->fifo_lock);
+	}
 
 	if ((masked_status & (SVGA_IRQFLAG_ANY_FENCE |
 			      SVGA_IRQFLAG_FENCE_GOAL)) &&
@@ -125,6 +132,8 @@ void vmw_update_seqno(struct vmw_private
 	u32 *fifo_mem = dev_priv->mmio_virt;
 	uint32_t seqno = vmw_mmio_read(fifo_mem + SVGA_FIFO_FENCE);
 
+	assert_spin_locked(&dev_priv->fence_lock);
+
 	if (dev_priv->last_read_seqno != seqno) {
 		dev_priv->last_read_seqno = seqno;
 		vmw_marker_pull(&fifo_state->marker_queue, seqno);
@@ -138,6 +147,8 @@ bool vmw_seqno_passed(struct vmw_private
 	struct vmw_fifo_state *fifo_state;
 	bool ret;
 
+	assert_spin_locked(&dev_priv->fence_lock);
+
 	if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
 		return true;
 
@@ -175,7 +186,9 @@ int vmw_fallback_wait(struct vmw_private
 	int ret;
 	unsigned long end_jiffies = jiffies + timeout;
 	bool (*wait_condition)(struct vmw_private *, uint32_t);
+#ifndef __NetBSD__
 	DEFINE_WAIT(__wait);
+#endif
 
 	wait_condition = (fifo_idle) ? &vmw_fifo_idle :
 		&vmw_seqno_passed;
@@ -194,10 +207,40 @@ int vmw_fallback_wait(struct vmw_private
 		}
 	}
 
+	spin_lock(&dev_priv->fence_lock);
+
 	signal_seq = atomic_read(&dev_priv->marker_seq);
 	ret = 0;
 
 	for (;;) {
+#ifdef __NetBSD__
+		if (!lazy) {
+			if (wait_condition(dev_priv, seqno))
+				break;
+			spin_unlock(&dev_priv->fence_lock);
+			if ((++count & 0xf) == 0)
+				yield();
+			spin_lock(&dev_priv->fence_lock);
+		} else if (interruptible) {
+			DRM_SPIN_TIMED_WAIT_UNTIL(ret, &dev_priv->fence_queue,
+			    &dev_priv->fence_lock, /*timeout*/1,
+			    wait_condition(dev_priv, seqno));
+		} else {
+			DRM_SPIN_TIMED_WAIT_NOINTR_UNTIL(ret,
+			    &dev_priv->fence_queue,
+			    &dev_priv->fence_lock, /*timeout*/1,
+			    wait_condition(dev_priv, seqno));
+		}
+		if (ret) {	/* success or error but not timeout */
+			if (ret > 0) /* success */
+				ret = 0;
+			break;
+		}
+		if (time_after_eq(jiffies, end_jiffies)) {
+			DRM_ERROR("SVGA device lockup.\n");
+			break;
+		}
+#else
 		prepare_to_wait(&dev_priv->fence_queue, &__wait,
 				(interruptible) ?
 				TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
@@ -225,14 +268,22 @@ int vmw_fallback_wait(struct vmw_private
 			ret = -ERESTARTSYS;
 			break;
 		}
+#endif
 	}
+#ifndef __NetBSD__
 	finish_wait(&dev_priv->fence_queue, &__wait);
+#endif
 	if (ret == 0 && fifo_idle) {
 		u32 *fifo_mem = dev_priv->mmio_virt;
 
 		vmw_mmio_write(signal_seq, fifo_mem + SVGA_FIFO_FENCE);
 	}
+#ifdef __NetBSD__
+	DRM_SPIN_WAKEUP_ALL(&dev_priv->fence_queue, &dev_priv->fence_lock);
+	spin_unlock(&dev_priv->fence_lock);
+#else
 	wake_up_all(&dev_priv->fence_queue);
+#endif
 out_err:
 	if (fifo_idle)
 		up_read(&fifo_state->rwsem);
@@ -294,37 +345,46 @@ int vmw_wait_seqno(struct vmw_private *d
 	long ret;
 	struct vmw_fifo_state *fifo = &dev_priv->fifo;
 
-	if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
+	spin_lock(&dev_priv->fence_lock);
+	if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP)) {
+		spin_unlock(&dev_priv->fence_lock);
 		return 0;
+	}
 
-	if (likely(vmw_seqno_passed(dev_priv, seqno)))
+	if (likely(vmw_seqno_passed(dev_priv, seqno))) {
+		spin_unlock(&dev_priv->fence_lock);
 		return 0;
+	}
 
 	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
 
-	if (!(fifo->capabilities & SVGA_FIFO_CAP_FENCE))
+	if (!(fifo->capabilities & SVGA_FIFO_CAP_FENCE)) {
+		spin_unlock(&dev_priv->fence_lock);
 		return vmw_fallback_wait(dev_priv, lazy, true, seqno,
 					 interruptible, timeout);
+	}
 
-	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
+	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK)) {
+		spin_unlock(&dev_priv->fence_lock);
 		return vmw_fallback_wait(dev_priv, lazy, false, seqno,
 					 interruptible, timeout);
+	}
 
 	vmw_seqno_waiter_add(dev_priv);
 
 	if (interruptible)
-		ret = wait_event_interruptible_timeout
-		    (dev_priv->fence_queue,
-		     vmw_seqno_passed(dev_priv, seqno),
-		     timeout);
+		DRM_SPIN_TIMED_WAIT_UNTIL(ret, &dev_priv->fence_queue,
+		    &dev_priv->fence_lock, timeout,
+		    vmw_seqno_passed(dev_priv, seqno));
 	else
-		ret = wait_event_timeout
-		    (dev_priv->fence_queue,
-		     vmw_seqno_passed(dev_priv, seqno),
-		     timeout);
+		DRM_SPIN_TIMED_WAIT_NOINTR_UNTIL(ret, &dev_priv->fence_queue,
+		    &dev_priv->fence_lock, timeout,
+		    vmw_seqno_passed(dev_priv, seqno));
 
 	vmw_seqno_waiter_remove(dev_priv);
 
+	spin_unlock(&dev_priv->fence_lock);
+
 	if (unlikely(ret == 0))
 		ret = -EBUSY;
 	else if (likely(ret > 0))

Reply via email to