summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nvif/chan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvif/chan.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvif/chan.c33
1 files changed, 31 insertions, 2 deletions
diff --git a/drivers/gpu/drm/nouveau/nvif/chan.c b/drivers/gpu/drm/nouveau/nvif/chan.c
index 7f58a1c17979..baa10227d51a 100644
--- a/drivers/gpu/drm/nouveau/nvif/chan.c
+++ b/drivers/gpu/drm/nouveau/nvif/chan.c
@@ -9,7 +9,16 @@ nvif_chan_gpfifo_push_kick(struct nvif_push *push)
{
struct nvif_chan *chan = container_of(push, typeof(*chan), push);
u32 put = push->bgn - (u32 *)chan->push.mem.object.map.ptr;
- u32 cnt = push->cur - push->bgn;
+ u32 cnt;
+
+ if (chan->func->gpfifo.post) {
+ if (push->end - push->cur < chan->func->gpfifo.post_size)
+ push->end = push->cur + chan->func->gpfifo.post_size;
+
+ WARN_ON(nvif_chan_gpfifo_post(chan));
+ }
+
+ cnt = push->cur - push->bgn;
chan->func->gpfifo.push(chan, true, chan->push.addr + (put << 2), cnt << 2, false);
chan->func->gpfifo.kick(chan);
@@ -23,6 +32,16 @@ nvif_chan_gpfifo_push_wait(struct nvif_push *push, u32 push_nr)
return nvif_chan_gpfifo_wait(chan, 1, push_nr);
}
+int
+nvif_chan_gpfifo_post(struct nvif_chan *chan)
+{
+ const u32 *map = chan->push.mem.object.map.ptr;
+ const u32 pbptr = (chan->push.cur - map) + chan->func->gpfifo.post_size;
+ const u32 gpptr = (chan->gpfifo.cur + 1) & chan->gpfifo.max;
+
+ return chan->func->gpfifo.post(chan, gpptr, pbptr);
+}
+
void
nvif_chan_gpfifo_push(struct nvif_chan *chan, u64 addr, u32 size, bool no_prefetch)
{
@@ -35,6 +54,14 @@ nvif_chan_gpfifo_wait(struct nvif_chan *chan, u32 gpfifo_nr, u32 push_nr)
struct nvif_push *push = &chan->push;
int ret = 0, time = 1000000;
+ if (gpfifo_nr) {
+ /* Account for pushbuf space needed by nvif_chan_gpfifo_post(),
+ * if used after pushing userspace GPFIFO entries.
+ */
+ if (chan->func->gpfifo.post)
+ push_nr += chan->func->gpfifo.post_size;
+ }
+
/* Account for the GPFIFO entry needed to submit pushbuf. */
if (push_nr)
gpfifo_nr++;
@@ -89,6 +116,8 @@ nvif_chan_dma_wait(struct nvif_chan *chan, u32 nr)
u32 cur = push->cur - (u32 *)push->mem.object.map.ptr;
u32 free, time = 1000000;
+ nr += chan->func->gpfifo.post_size;
+
do {
u32 get = chan->func->push.read_get(chan);
@@ -122,6 +151,6 @@ nvif_chan_dma_wait(struct nvif_chan *chan, u32 nr)
push->bgn = (u32 *)push->mem.object.map.ptr + cur;
push->cur = push->bgn;
- push->end = push->bgn + free;
+ push->end = push->bgn + free - chan->func->gpfifo.post_size;
return 0;
}