drm/vmwgfx: Fix a circular locking dependency bug.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
index 4157547..39d43a0 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
@@ -74,6 +74,7 @@
 	fifo->reserved_size = 0;
 	fifo->using_bounce_buffer = false;
 
+	mutex_init(&fifo->fifo_mutex);
 	init_rwsem(&fifo->rwsem);
 
 	/*
@@ -117,7 +118,7 @@
 		 (unsigned int) min,
 		 (unsigned int) fifo->capabilities);
 
-	dev_priv->fence_seq = dev_priv->last_read_sequence;
+	atomic_set(&dev_priv->fence_seq, dev_priv->last_read_sequence);
 	iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE);
 
 	return vmw_fifo_send_fence(dev_priv, &dummy);
@@ -283,7 +284,7 @@
 	uint32_t reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE;
 	int ret;
 
-	down_write(&fifo_state->rwsem);
+	mutex_lock(&fifo_state->fifo_mutex);
 	max = ioread32(fifo_mem + SVGA_FIFO_MAX);
 	min = ioread32(fifo_mem + SVGA_FIFO_MIN);
 	next_cmd = ioread32(fifo_mem + SVGA_FIFO_NEXT_CMD);
@@ -351,7 +352,7 @@
 	}
 out_err:
 	fifo_state->reserved_size = 0;
-	up_write(&fifo_state->rwsem);
+	mutex_unlock(&fifo_state->fifo_mutex);
 	return NULL;
 }
 
@@ -426,6 +427,7 @@
 
 	}
 
+	down_write(&fifo_state->rwsem);
 	if (fifo_state->using_bounce_buffer || reserveable) {
 		next_cmd += bytes;
 		if (next_cmd >= max)
@@ -437,8 +439,9 @@
 	if (reserveable)
 		iowrite32(0, fifo_mem + SVGA_FIFO_RESERVED);
 	mb();
-	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
 	up_write(&fifo_state->rwsem);
+	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
+	mutex_unlock(&fifo_state->fifo_mutex);
 }
 
 int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence)
@@ -451,9 +454,7 @@
 
 	fm = vmw_fifo_reserve(dev_priv, bytes);
 	if (unlikely(fm == NULL)) {
-		down_write(&fifo_state->rwsem);
-		*sequence = dev_priv->fence_seq;
-		up_write(&fifo_state->rwsem);
+		*sequence = atomic_read(&dev_priv->fence_seq);
 		ret = -ENOMEM;
 		(void)vmw_fallback_wait(dev_priv, false, true, *sequence,
 					false, 3*HZ);
@@ -461,7 +462,7 @@
 	}
 
 	do {
-		*sequence = dev_priv->fence_seq++;
+		*sequence = atomic_add_return(1, &dev_priv->fence_seq);
 	} while (*sequence == 0);
 
 	if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE)) {