[Nouveau] [PATCH 4/4] drm/nouveau: fix ring buffer wrap-around

Pekka Paalanen pq at iki.fi
Thu Aug 20 11:11:36 PDT 2009


In the wrap around case, it was resetting to SKIPS + 1, which would
leave one dword after the actual SKIPs untouched. It is a bit odd that
the undefined dword has not caused real trouble, or perhaps it is
written a "safe" value by accident.

Rename dma_wait_ring_wrap() to ring_wrap() and clean it up. Make
the dma.free computation just like in nouveau_dma_free().

Signed-off-by: Pekka Paalanen <pq at iki.fi>
---
 drivers/gpu/drm/nouveau/nouveau_dma.c |   22 +++++++++-------------
 1 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c
index 28e9c11..5ede79c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.c
@@ -115,33 +115,31 @@ READ_GET(struct nouveau_channel *chan, uint32_t *get)
 	return true;
 }
 
-static int
-dma_wait_ring_wrap(struct nouveau_channel *chan, int size, uint32_t get,
-		   int *timeout)
+static void
+ring_wrap(struct nouveau_channel *chan, int size, uint32_t get, int *timeout)
 {
 	/* Emit jump to the start of the ring buffer. */
 	OUT_RING(chan, 0x20000000 | chan->pushbuf_base);
 
-	if (get <= NOUVEAU_DMA_SKIPS) {
+	if (get < NOUVEAU_DMA_SKIPS) {
 		/* corner case - will be idle */
-		if (chan->dma.put <= NOUVEAU_DMA_SKIPS)
-			WRITE_PUT(chan, NOUVEAU_DMA_SKIPS + 1);
+		if (chan->dma.put < NOUVEAU_DMA_SKIPS)
+			WRITE_PUT(chan, NOUVEAU_DMA_SKIPS);
 
 		for (; *timeout; (*timeout)--) {
-			if (READ_GET(chan, &get) && get > NOUVEAU_DMA_SKIPS)
+			if (READ_GET(chan, &get) && get >= NOUVEAU_DMA_SKIPS)
 				break;
 
 			DRM_UDELAY(1);
 		}
 
 		if (*timeout == 0)
-			return -EBUSY;
+			return;
 	}
 
 	WRITE_PUT(chan, NOUVEAU_DMA_SKIPS);
 	chan->dma.cur  = NOUVEAU_DMA_SKIPS;
-	chan->dma.free = get - (NOUVEAU_DMA_SKIPS + 1);
-	return 0;
+	chan->dma.free = get - chan->dma.cur - 1;
 }
 
 int
@@ -160,9 +158,7 @@ nouveau_dma_wait(struct nouveau_channel *chan, int size)
 			chan->dma.free = chan->dma.max - chan->dma.cur;
 
 			if (chan->dma.free < size)
-				if (dma_wait_ring_wrap(chan, size, get,
-								&us_timeout))
-					return -EBUSY;
+				ring_wrap(chan, size, get, &us_timeout);
 		} else {
 			chan->dma.free = get - chan->dma.cur - 1;
 		}
-- 
1.6.3.3



More information about the Nouveau mailing list