aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2013-01-30 23:57:33 -0500
committerBen Skeggs <bskeggs@redhat.com>2013-02-20 01:00:48 -0500
commite18c080fb8695d038f69c26c248f5ecbd9e8aa77 (patch)
tree74e191678bb9ba028d85e219863ddb706f4e6fc8 /drivers
parenta2fa297378c54e9b8b8ad355e34c9fbed730250b (diff)
drm/nouveau/fence/nv84-: put processes to sleep while waiting on fences
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dma.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c76
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.h3
-rw-r--r--drivers/gpu/drm/nouveau/nv84_fence.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fence.c8
5 files changed, 92 insertions, 5 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h
index 5c2e22932d1c..690d5930ce32 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.h
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.h
@@ -191,7 +191,7 @@ WIND_RING(struct nouveau_channel *chan)
191#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG 0x00000002 191#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG 0x00000002
192#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL 0x00000004 192#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL 0x00000004
193#define NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD 0x00001000 193#define NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD 0x00001000
194#define NV84_SUBCHAN_NOTIFY_INTR 0x00000020 194#define NV84_SUBCHAN_UEVENT 0x00000020
195#define NV84_SUBCHAN_WRCACHE_FLUSH 0x00000024 195#define NV84_SUBCHAN_WRCACHE_FLUSH 0x00000024
196#define NV10_SUBCHAN_REF_CNT 0x00000050 196#define NV10_SUBCHAN_REF_CNT 0x00000050
197#define NVSW_SUBCHAN_PAGE_FLIP 0x00000054 197#define NVSW_SUBCHAN_PAGE_FLIP 0x00000054
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index b6b8e49ac68f..b7349a636546 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -33,6 +33,8 @@
33#include "nouveau_dma.h" 33#include "nouveau_dma.h"
34#include "nouveau_fence.h" 34#include "nouveau_fence.h"
35 35
36#include <engine/fifo.h>
37
36void 38void
37nouveau_fence_context_del(struct nouveau_fence_chan *fctx) 39nouveau_fence_context_del(struct nouveau_fence_chan *fctx)
38{ 40{
@@ -107,13 +109,87 @@ nouveau_fence_done(struct nouveau_fence *fence)
107 return !fence->channel; 109 return !fence->channel;
108} 110}
109 111
112struct nouveau_fence_uevent {
113 struct nouveau_eventh handler;
114 struct nouveau_fence_priv *priv;
115};
116
117static int
118nouveau_fence_wait_uevent_handler(struct nouveau_eventh *event, int index)
119{
120 struct nouveau_fence_uevent *uevent =
121 container_of(event, struct nouveau_fence_uevent, handler);
122 wake_up_all(&uevent->priv->waiting);
123 return NVKM_EVENT_KEEP;
124}
125
126static int
127nouveau_fence_wait_uevent(struct nouveau_fence *fence, bool intr)
128
129{
130 struct nouveau_channel *chan = fence->channel;
131 struct nouveau_fifo *pfifo = nouveau_fifo(chan->drm->device);
132 struct nouveau_fence_priv *priv = chan->drm->fence;
133 struct nouveau_fence_uevent uevent = {
134 .handler.func = nouveau_fence_wait_uevent_handler,
135 .priv = priv,
136 };
137 int ret = 0;
138
139 nouveau_event_get(pfifo->uevent, 0, &uevent.handler);
140
141 if (fence->timeout) {
142 unsigned long timeout = fence->timeout - jiffies;
143
144 if (time_before(jiffies, fence->timeout)) {
145 if (intr) {
146 ret = wait_event_interruptible_timeout(
147 priv->waiting,
148 nouveau_fence_done(fence),
149 timeout);
150 } else {
151 ret = wait_event_timeout(priv->waiting,
152 nouveau_fence_done(fence),
153 timeout);
154 }
155 }
156
157 if (ret >= 0) {
158 fence->timeout = jiffies + ret;
159 if (time_after_eq(jiffies, fence->timeout))
160 ret = -EBUSY;
161 }
162 } else {
163 if (intr) {
164 ret = wait_event_interruptible(priv->waiting,
165 nouveau_fence_done(fence));
166 } else {
167 wait_event(priv->waiting, nouveau_fence_done(fence));
168 }
169 }
170
171 nouveau_event_put(pfifo->uevent, 0, &uevent.handler);
172 if (unlikely(ret < 0))
173 return ret;
174
175 return 0;
176}
177
110int 178int
111nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr) 179nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr)
112{ 180{
181 struct nouveau_channel *chan = fence->channel;
182 struct nouveau_fence_priv *priv = chan ? chan->drm->fence : NULL;
113 unsigned long sleep_time = NSEC_PER_MSEC / 1000; 183 unsigned long sleep_time = NSEC_PER_MSEC / 1000;
114 ktime_t t; 184 ktime_t t;
115 int ret = 0; 185 int ret = 0;
116 186
187 while (priv && priv->uevent && lazy && !nouveau_fence_done(fence)) {
188 ret = nouveau_fence_wait_uevent(fence, intr);
189 if (ret < 0)
190 return ret;
191 }
192
117 while (!nouveau_fence_done(fence)) { 193 while (!nouveau_fence_done(fence)) {
118 if (fence->timeout && time_after_eq(jiffies, fence->timeout)) { 194 if (fence->timeout && time_after_eq(jiffies, fence->timeout)) {
119 ret = -EBUSY; 195 ret = -EBUSY;
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h
index cdb83acdffe2..be6166eb966d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.h
@@ -43,6 +43,9 @@ struct nouveau_fence_priv {
43 int (*sync)(struct nouveau_fence *, struct nouveau_channel *, 43 int (*sync)(struct nouveau_fence *, struct nouveau_channel *,
44 struct nouveau_channel *); 44 struct nouveau_channel *);
45 u32 (*read)(struct nouveau_channel *); 45 u32 (*read)(struct nouveau_channel *);
46
47 wait_queue_head_t waiting;
48 bool uevent;
46}; 49};
47 50
48#define nouveau_fence(drm) ((struct nouveau_fence_priv *)(drm)->fence) 51#define nouveau_fence(drm) ((struct nouveau_fence_priv *)(drm)->fence)
diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c
index c686650584b6..e64e8154a5af 100644
--- a/drivers/gpu/drm/nouveau/nv84_fence.c
+++ b/drivers/gpu/drm/nouveau/nv84_fence.c
@@ -47,15 +47,16 @@ nv84_fence_emit(struct nouveau_fence *fence)
47{ 47{
48 struct nouveau_channel *chan = fence->channel; 48 struct nouveau_channel *chan = fence->channel;
49 struct nouveau_fifo_chan *fifo = (void *)chan->object; 49 struct nouveau_fifo_chan *fifo = (void *)chan->object;
50 int ret = RING_SPACE(chan, 7); 50 int ret = RING_SPACE(chan, 8);
51 if (ret == 0) { 51 if (ret == 0) {
52 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); 52 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
53 OUT_RING (chan, NvSema); 53 OUT_RING (chan, NvSema);
54 BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 54 BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 5);
55 OUT_RING (chan, upper_32_bits(fifo->chid * 16)); 55 OUT_RING (chan, upper_32_bits(fifo->chid * 16));
56 OUT_RING (chan, lower_32_bits(fifo->chid * 16)); 56 OUT_RING (chan, lower_32_bits(fifo->chid * 16));
57 OUT_RING (chan, fence->sequence); 57 OUT_RING (chan, fence->sequence);
58 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG); 58 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG);
59 OUT_RING (chan, 0x00000000);
59 FIRE_RING (chan); 60 FIRE_RING (chan);
60 } 61 }
61 return ret; 62 return ret;
@@ -174,6 +175,9 @@ nv84_fence_create(struct nouveau_drm *drm)
174 priv->base.sync = nv84_fence_sync; 175 priv->base.sync = nv84_fence_sync;
175 priv->base.read = nv84_fence_read; 176 priv->base.read = nv84_fence_read;
176 177
178 init_waitqueue_head(&priv->base.waiting);
179 priv->base.uevent = true;
180
177 ret = nouveau_gpuobj_new(drm->device, NULL, chan * 16, 0x1000, 0, 181 ret = nouveau_gpuobj_new(drm->device, NULL, chan * 16, 0x1000, 0,
178 &priv->mem); 182 &priv->mem);
179 if (ret) 183 if (ret)
diff --git a/drivers/gpu/drm/nouveau/nvc0_fence.c b/drivers/gpu/drm/nouveau/nvc0_fence.c
index 2a56b1b551cb..d8ed2c5f4fab 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fence.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fence.c
@@ -62,13 +62,14 @@ nvc0_fence_emit(struct nouveau_fence *fence)
62 u64 addr = fctx->vma.offset + fifo->chid * 16; 62 u64 addr = fctx->vma.offset + fifo->chid * 16;
63 int ret; 63 int ret;
64 64
65 ret = RING_SPACE(chan, 5); 65 ret = RING_SPACE(chan, 6);
66 if (ret == 0) { 66 if (ret == 0) {
67 BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 67 BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 5);
68 OUT_RING (chan, upper_32_bits(addr)); 68 OUT_RING (chan, upper_32_bits(addr));
69 OUT_RING (chan, lower_32_bits(addr)); 69 OUT_RING (chan, lower_32_bits(addr));
70 OUT_RING (chan, fence->sequence); 70 OUT_RING (chan, fence->sequence);
71 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG); 71 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG);
72 OUT_RING (chan, 0x00000000);
72 FIRE_RING (chan); 73 FIRE_RING (chan);
73 } 74 }
74 75
@@ -217,6 +218,9 @@ nvc0_fence_create(struct nouveau_drm *drm)
217 priv->base.sync = nvc0_fence_sync; 218 priv->base.sync = nvc0_fence_sync;
218 priv->base.read = nvc0_fence_read; 219 priv->base.read = nvc0_fence_read;
219 220
221 init_waitqueue_head(&priv->base.waiting);
222 priv->base.uevent = true;
223
220 ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0, 224 ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0,
221 TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo); 225 TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo);
222 if (ret == 0) { 226 if (ret == 0) {