summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nvc0
diff options
context:
space:
mode:
authorChristoph Bumiller <[email protected]>2011-09-13 23:02:23 +0200
committerChristoph Bumiller <[email protected]>2011-09-14 16:19:52 +0200
commita42eca84c56f6860e67c0c57f4765a5530cc5f81 (patch)
tree0aab5c468d0794e1e9d93c493ff5e98da8626f5b /src/gallium/drivers/nvc0
parent150bb0fb34b74055c7dd6d2925ce9c5a1d7decf5 (diff)
nvc0: prevent interruption of m2mf push
M2MF will trap if the data stream is interrupted by a QUERY fence and report too much or not enough data.
Diffstat (limited to 'src/gallium/drivers/nvc0')
-rw-r--r--src/gallium/drivers/nvc0/nvc0_transfer.c38
1 files changed, 18 insertions, 20 deletions
diff --git a/src/gallium/drivers/nvc0/nvc0_transfer.c b/src/gallium/drivers/nvc0/nvc0_transfer.c
index 69d4a90ed3d..6404c8cc4ae 100644
--- a/src/gallium/drivers/nvc0/nvc0_transfer.c
+++ b/src/gallium/drivers/nvc0/nvc0_transfer.c
@@ -111,33 +111,31 @@ nvc0_m2mf_push_linear(struct nouveau_context *nv,
uint32_t *src = (uint32_t *)data;
unsigned count = (size + 3) / 4;
- MARK_RING (chan, 8, 2);
-
- BEGIN_RING(chan, RING_MF(OFFSET_OUT_HIGH), 2);
- OUT_RELOCh(chan, dst, offset, domain | NOUVEAU_BO_WR);
- OUT_RELOCl(chan, dst, offset, domain | NOUVEAU_BO_WR);
- BEGIN_RING(chan, RING_MF(LINE_LENGTH_IN), 2);
- OUT_RING (chan, size);
- OUT_RING (chan, 1);
- BEGIN_RING(chan, RING_MF(EXEC), 1);
- OUT_RING (chan, 0x100111);
-
while (count) {
- unsigned nr = AVAIL_RING(chan);
+ unsigned nr;
- if (nr < 9) {
- FIRE_RING(chan);
- nouveau_bo_validate(chan, dst, NOUVEAU_BO_WR);
- continue;
- }
- nr = MIN2(count, nr - 1);
+ MARK_RING (chan, 16, 2);
+
+ nr = AVAIL_RING(chan) - 9;
+ nr = MIN2(count, nr);
nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN);
-
+
+ BEGIN_RING(chan, RING_MF(OFFSET_OUT_HIGH), 2);
+ OUT_RELOCh(chan, dst, offset, domain | NOUVEAU_BO_WR);
+ OUT_RELOCl(chan, dst, offset, domain | NOUVEAU_BO_WR);
+ BEGIN_RING(chan, RING_MF(LINE_LENGTH_IN), 2);
+ OUT_RING (chan, nr * 4);
+ OUT_RING (chan, 1);
+ BEGIN_RING(chan, RING_MF(EXEC), 1);
+ OUT_RING (chan, 0x100111);
+
+ /* must not be interrupted (trap on QUERY fence, 0x50 works however) */
BEGIN_RING_NI(chan, RING_MF(DATA), nr);
OUT_RINGp (chan, src, nr);
- src += nr;
count -= nr;
+ src += nr;
+ offset += nr * 4;
}
}