diff options
author | Christoph Bumiller <[email protected]> | 2011-09-13 23:02:23 +0200 |
---|---|---|
committer | Christoph Bumiller <[email protected]> | 2011-09-14 16:19:52 +0200 |
commit | a42eca84c56f6860e67c0c57f4765a5530cc5f81 (patch) | |
tree | 0aab5c468d0794e1e9d93c493ff5e98da8626f5b | |
parent | 150bb0fb34b74055c7dd6d2925ce9c5a1d7decf5 (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.
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_transfer.c | 38 |
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; } } |