All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] drm/nouveau: refactor nouveau_dma_wait()
@ 2009-08-20 18:11 Pekka Paalanen
       [not found] ` <1250791896-15510-1-git-send-email-pq-X3B1VOXEql0@public.gmane.org>
  0 siblings, 1 reply; 5+ messages in thread
From: Pekka Paalanen @ 2009-08-20 18:11 UTC (permalink / raw)
  To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

A cleanup of nouveau_dma_wait(): extract a sub-function and eliminate
two variables to improve readability.

No functional changes.

Signed-off-by: Pekka Paalanen <pq-X3B1VOXEql0@public.gmane.org>
---
 drivers/gpu/drm/nouveau/nouveau_dma.c |   72 ++++++++++++++++++---------------
 1 files changed, 39 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c
index b1f3a71..b787651 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.c
@@ -115,14 +115,43 @@ 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)
+{
+	/* Emit jump to the start of the ring buffer. */
+	OUT_RING(chan, 0x20000000 | chan->pushbuf_base);
+
+	if (get <= NOUVEAU_DMA_SKIPS) {
+		/* corner case - will be idle */
+		if (chan->dma.put <= NOUVEAU_DMA_SKIPS)
+			WRITE_PUT(NOUVEAU_DMA_SKIPS + 1);
+
+		for (; *timeout; (*timeout)--) {
+			if (READ_GET(chan, &get) && get > NOUVEAU_DMA_SKIPS)
+				break;
+
+			DRM_UDELAY(1);
+		}
+
+		if (*timeout == 0)
+			return -EBUSY;
+	}
+
+	WRITE_PUT(NOUVEAU_DMA_SKIPS);
+	chan->dma.cur  = NOUVEAU_DMA_SKIPS;
+	chan->dma.put  = NOUVEAU_DMA_SKIPS;
+	chan->dma.free = get - (NOUVEAU_DMA_SKIPS + 1);
+	return 0;
+}
+
 int
 nouveau_dma_wait(struct nouveau_channel *chan, int size)
 {
-	const int us_timeout = 100000;
+	int us_timeout = 100000;
 	uint32_t get;
-	int ret = -EBUSY, i;
 
-	for (i = 0; i < us_timeout; i++) {
+	for (; us_timeout; us_timeout--) {
 		if (!READ_GET(chan, &get)) {
 			DRM_UDELAY(1);
 			continue;
@@ -131,41 +160,18 @@ nouveau_dma_wait(struct nouveau_channel *chan, int size)
 		if (chan->dma.put >= get) {
 			chan->dma.free = chan->dma.max - chan->dma.cur;
 
-			if (chan->dma.free < size) {
-				OUT_RING(chan, 0x20000000|chan->pushbuf_base);
-				if (get <= NOUVEAU_DMA_SKIPS) {
-					/*corner case - will be idle*/
-					if (chan->dma.put <= NOUVEAU_DMA_SKIPS)
-						WRITE_PUT(NOUVEAU_DMA_SKIPS + 1);
-
-					for (; i < us_timeout; i++) {
-						if (READ_GET(chan, &get) &&
-						    get > NOUVEAU_DMA_SKIPS)
-							break;
-
-						DRM_UDELAY(1);
-					}
-
-					if (i >= us_timeout)
-						break;
-				}
-
-				WRITE_PUT(NOUVEAU_DMA_SKIPS);
-				chan->dma.cur  =
-				chan->dma.put  = NOUVEAU_DMA_SKIPS;
-				chan->dma.free = get - (NOUVEAU_DMA_SKIPS + 1);
-			}
+			if (chan->dma.free < size)
+				if (dma_wait_ring_wrap(chan, size, get,
+								&us_timeout))
+					return -EBUSY;
 		} else {
 			chan->dma.free = get - chan->dma.cur - 1;
 		}
 
-		if (chan->dma.free >= size) {
-			ret = 0;
-			break;
-		}
+		if (chan->dma.free >= size)
+			return 0;
 
 		DRM_UDELAY(1);
 	}
-
-	return ret;
+	return -EBUSY;
 }
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] drm/nouveau: make WRITE_PUT a function
       [not found] ` <1250791896-15510-1-git-send-email-pq-X3B1VOXEql0@public.gmane.org>
@ 2009-08-20 18:11   ` Pekka Paalanen
       [not found]     ` <1250791896-15510-2-git-send-email-pq-X3B1VOXEql0@public.gmane.org>
  0 siblings, 1 reply; 5+ messages in thread
From: Pekka Paalanen @ 2009-08-20 18:11 UTC (permalink / raw)
  To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

Make WRITE_PUT() an inline function, and pass chan as an argument.
Update chan->dma.put in WRITE_PUT() instead of (almost) everywhere by
hand afterwards.

Signed-off-by: Pekka Paalanen <pq-X3B1VOXEql0@public.gmane.org>
---
 drivers/gpu/drm/nouveau/nouveau_dma.c |    5 ++---
 drivers/gpu/drm/nouveau/nouveau_dma.h |   16 +++++++++-------
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c
index b787651..28e9c11 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.c
@@ -125,7 +125,7 @@ dma_wait_ring_wrap(struct nouveau_channel *chan, int size, uint32_t get,
 	if (get <= NOUVEAU_DMA_SKIPS) {
 		/* corner case - will be idle */
 		if (chan->dma.put <= NOUVEAU_DMA_SKIPS)
-			WRITE_PUT(NOUVEAU_DMA_SKIPS + 1);
+			WRITE_PUT(chan, NOUVEAU_DMA_SKIPS + 1);
 
 		for (; *timeout; (*timeout)--) {
 			if (READ_GET(chan, &get) && get > NOUVEAU_DMA_SKIPS)
@@ -138,9 +138,8 @@ dma_wait_ring_wrap(struct nouveau_channel *chan, int size, uint32_t get,
 			return -EBUSY;
 	}
 
-	WRITE_PUT(NOUVEAU_DMA_SKIPS);
+	WRITE_PUT(chan, NOUVEAU_DMA_SKIPS);
 	chan->dma.cur  = NOUVEAU_DMA_SKIPS;
-	chan->dma.put  = NOUVEAU_DMA_SKIPS;
 	chan->dma.free = get - (NOUVEAU_DMA_SKIPS + 1);
 	return 0;
 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h
index cdaa37d..74db74e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.h
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.h
@@ -118,11 +118,14 @@ BEGIN_RING(struct nouveau_channel *chan, int subc, int mthd, int size)
 	OUT_RING(chan, (subc << 13) | (size << 18) | mthd);
 }
 
-#define WRITE_PUT(val) do {                                                    \
-	DRM_MEMORYBARRIER();                                                   \
-	nouveau_bo_rd32(chan->pushbuf_bo, 0);                                  \
-	nvchan_wr32(chan->user_put, ((val) << 2) + chan->pushbuf_base);        \
-} while (0)
+static inline void
+WRITE_PUT(struct nouveau_channel *chan, uint32_t index)
+{
+	DRM_MEMORYBARRIER();
+	nouveau_bo_rd32(chan->pushbuf_bo, 0);
+	nvchan_wr32(chan->user_put, index * 4 + chan->pushbuf_base);
+	chan->dma.put = index;
+}
 
 static inline void
 FIRE_RING(struct nouveau_channel *chan)
@@ -135,8 +138,7 @@ FIRE_RING(struct nouveau_channel *chan)
 		return;
 	chan->accel_done = true;
 
-	WRITE_PUT(chan->dma.cur);
-	chan->dma.put = chan->dma.cur;
+	WRITE_PUT(chan, chan->dma.cur);
 }
 
 static inline void
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] drm/nouveau: add PCI flush to FIRE_RING()
       [not found]     ` <1250791896-15510-2-git-send-email-pq-X3B1VOXEql0@public.gmane.org>
@ 2009-08-20 18:11       ` Pekka Paalanen
       [not found]         ` <1250791896-15510-3-git-send-email-pq-X3B1VOXEql0@public.gmane.org>
  0 siblings, 1 reply; 5+ messages in thread
From: Pekka Paalanen @ 2009-08-20 18:11 UTC (permalink / raw)
  To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

A PCI write may be cached somewhere in the a PCI bridge/bus for some
time. Doing a PCI read will force all pending writes to be finished.

Add a dummy read to force the PUT register write to arrive to hardware
at FIRE_RING time.

Add comments for the barrier and flush in WRITE_PUT().

Signed-off-by: Pekka Paalanen <pq-X3B1VOXEql0@public.gmane.org>
---
 drivers/gpu/drm/nouveau/nouveau_dma.h |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h
index 74db74e..aada9be 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.h
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.h
@@ -121,8 +121,13 @@ BEGIN_RING(struct nouveau_channel *chan, int subc, int mthd, int size)
 static inline void
 WRITE_PUT(struct nouveau_channel *chan, uint32_t index)
 {
+	/* no CPU instruction reordering over this point */
 	DRM_MEMORYBARRIER();
-	nouveau_bo_rd32(chan->pushbuf_bo, 0);
+
+	/* flush pushbuf writes, if it happens to be in VRAM */
+	(void)nouveau_bo_rd32(chan->pushbuf_bo, 0);
+
+	/* fire */
 	nvchan_wr32(chan->user_put, index * 4 + chan->pushbuf_base);
 	chan->dma.put = index;
 }
@@ -139,6 +144,9 @@ FIRE_RING(struct nouveau_channel *chan)
 	chan->accel_done = true;
 
 	WRITE_PUT(chan, chan->dma.cur);
+
+	/* flush the fire PCI write to the card */
+	(void)nvchan_rd32(chan->user_get);
 }
 
 static inline void
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] drm/nouveau: fix ring buffer wrap-around
       [not found]         ` <1250791896-15510-3-git-send-email-pq-X3B1VOXEql0@public.gmane.org>
@ 2009-08-20 18:11           ` Pekka Paalanen
       [not found]             ` <6d4bc9fc0908201127r31db8153r36868ea96a624f30@mail.gmail.com>
  0 siblings, 1 reply; 5+ messages in thread
From: Pekka Paalanen @ 2009-08-20 18:11 UTC (permalink / raw)
  To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

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-X3B1VOXEql0@public.gmane.org>
---
 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

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 4/4] drm/nouveau: fix ring buffer wrap-around
       [not found]                 ` <20090821075823.31443f49-cxYvVS3buNOdIgDiPM52R8c4bpwCjbIv@public.gmane.org>
@ 2009-08-21 10:38                   ` Maarten Maathuis
  0 siblings, 0 replies; 5+ messages in thread
From: Maarten Maathuis @ 2009-08-21 10:38 UTC (permalink / raw)
  To: Pekka Paalanen; +Cc: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On Fri, Aug 21, 2009 at 6:58 AM, Pekka Paalanen<pq-X3B1VOXEql0@public.gmane.org> wrote:
> On Thu, 20 Aug 2009 20:27:49 +0200
> Maarten Maathuis <madman2003-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>
>> I think the -1 on chan->dma.free is unnecessary.
>
> Maybe it is for the wrap-around jump command, the OUT_RING?
> I don't any other way of reserving memory for writing that.

The initial pushbuf size is deducted by 2, because nv50 needs it for
some reason.
Originally it was 1, to accommodate the jump.

>
> --
> Pekka Paalanen
> http://www.iki.fi/pq/
>

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2009-08-21 10:38 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-08-20 18:11 [PATCH 1/4] drm/nouveau: refactor nouveau_dma_wait() Pekka Paalanen
     [not found] ` <1250791896-15510-1-git-send-email-pq-X3B1VOXEql0@public.gmane.org>
2009-08-20 18:11   ` [PATCH 2/4] drm/nouveau: make WRITE_PUT a function Pekka Paalanen
     [not found]     ` <1250791896-15510-2-git-send-email-pq-X3B1VOXEql0@public.gmane.org>
2009-08-20 18:11       ` [PATCH 3/4] drm/nouveau: add PCI flush to FIRE_RING() Pekka Paalanen
     [not found]         ` <1250791896-15510-3-git-send-email-pq-X3B1VOXEql0@public.gmane.org>
2009-08-20 18:11           ` [PATCH 4/4] drm/nouveau: fix ring buffer wrap-around Pekka Paalanen
     [not found]             ` <6d4bc9fc0908201127r31db8153r36868ea96a624f30@mail.gmail.com>
     [not found]               ` <20090821075823.31443f49@daedalus.pq.iki.fi>
     [not found]                 ` <20090821075823.31443f49-cxYvVS3buNOdIgDiPM52R8c4bpwCjbIv@public.gmane.org>
2009-08-21 10:38                   ` Maarten Maathuis

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.