aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2013-02-13 22:43:21 -0500
committerBen Skeggs <bskeggs@redhat.com>2013-02-20 01:00:53 -0500
commit264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30 (patch)
tree68ba7f61bc07f54378e562ce385f60dc814b4fad /drivers/gpu
parent827520ce06568f699dad275dcca61647cce08757 (diff)
drm/nv84-/fence: prepare for emit/sync support of sysram sequences
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c9
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.h18
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv84_fence.c59
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fence.c33
8 files changed, 65 insertions, 62 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 69d7b1d0b9d6..fce944c17a55 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -561,7 +561,7 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
561 struct nouveau_fence *fence = NULL; 561 struct nouveau_fence *fence = NULL;
562 int ret; 562 int ret;
563 563
564 ret = nouveau_fence_new(chan, &fence); 564 ret = nouveau_fence_new(chan, false, &fence);
565 if (ret) 565 if (ret)
566 return ret; 566 return ret;
567 567
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c
index 525a5177b622..eaa80a2b81ee 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.c
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.c
@@ -51,7 +51,7 @@ nouveau_channel_idle(struct nouveau_channel *chan)
51 struct nouveau_fence *fence = NULL; 51 struct nouveau_fence *fence = NULL;
52 int ret; 52 int ret;
53 53
54 ret = nouveau_fence_new(chan, &fence); 54 ret = nouveau_fence_new(chan, false, &fence);
55 if (!ret) { 55 if (!ret) {
56 ret = nouveau_fence_wait(fence, false, false); 56 ret = nouveau_fence_wait(fence, false, false);
57 nouveau_fence_unref(&fence); 57 nouveau_fence_unref(&fence);
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 78fc5aa5f5dc..de87417a8167 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -540,7 +540,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
540 } 540 }
541 FIRE_RING (chan); 541 FIRE_RING (chan);
542 542
543 ret = nouveau_fence_new(chan, pfence); 543 ret = nouveau_fence_new(chan, false, pfence);
544 if (ret) 544 if (ret)
545 goto fail; 545 goto fail;
546 546
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index 6a7a5b576273..6c946837a0aa 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -41,8 +41,6 @@ nouveau_fence_context_del(struct nouveau_fence_chan *fctx)
41 struct nouveau_fence *fence, *fnext; 41 struct nouveau_fence *fence, *fnext;
42 spin_lock(&fctx->lock); 42 spin_lock(&fctx->lock);
43 list_for_each_entry_safe(fence, fnext, &fctx->pending, head) { 43 list_for_each_entry_safe(fence, fnext, &fctx->pending, head) {
44 if (fence->work)
45 fence->work(fence->priv, false);
46 fence->channel = NULL; 44 fence->channel = NULL;
47 list_del(&fence->head); 45 list_del(&fence->head);
48 nouveau_fence_unref(&fence); 46 nouveau_fence_unref(&fence);
@@ -69,8 +67,6 @@ nouveau_fence_update(struct nouveau_channel *chan)
69 if (fctx->read(chan) < fence->sequence) 67 if (fctx->read(chan) < fence->sequence)
70 break; 68 break;
71 69
72 if (fence->work)
73 fence->work(fence->priv, true);
74 fence->channel = NULL; 70 fence->channel = NULL;
75 list_del(&fence->head); 71 list_del(&fence->head);
76 nouveau_fence_unref(&fence); 72 nouveau_fence_unref(&fence);
@@ -256,7 +252,8 @@ nouveau_fence_ref(struct nouveau_fence *fence)
256} 252}
257 253
258int 254int
259nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence) 255nouveau_fence_new(struct nouveau_channel *chan, bool sysmem,
256 struct nouveau_fence **pfence)
260{ 257{
261 struct nouveau_fence *fence; 258 struct nouveau_fence *fence;
262 int ret = 0; 259 int ret = 0;
@@ -267,6 +264,8 @@ nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence)
267 fence = kzalloc(sizeof(*fence), GFP_KERNEL); 264 fence = kzalloc(sizeof(*fence), GFP_KERNEL);
268 if (!fence) 265 if (!fence)
269 return -ENOMEM; 266 return -ENOMEM;
267
268 fence->sysmem = sysmem;
270 kref_init(&fence->kref); 269 kref_init(&fence->kref);
271 270
272 ret = nouveau_fence_emit(fence, chan); 271 ret = nouveau_fence_emit(fence, chan);
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h
index a5c47e348e22..c89943407b52 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.h
@@ -7,15 +7,15 @@ struct nouveau_fence {
7 struct list_head head; 7 struct list_head head;
8 struct kref kref; 8 struct kref kref;
9 9
10 bool sysmem;
11
10 struct nouveau_channel *channel; 12 struct nouveau_channel *channel;
11 unsigned long timeout; 13 unsigned long timeout;
12 u32 sequence; 14 u32 sequence;
13
14 void (*work)(void *priv, bool signalled);
15 void *priv;
16}; 15};
17 16
18int nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **); 17int nouveau_fence_new(struct nouveau_channel *, bool sysmem,
18 struct nouveau_fence **);
19struct nouveau_fence * 19struct nouveau_fence *
20nouveau_fence_ref(struct nouveau_fence *); 20nouveau_fence_ref(struct nouveau_fence *);
21void nouveau_fence_unref(struct nouveau_fence **); 21void nouveau_fence_unref(struct nouveau_fence **);
@@ -79,24 +79,18 @@ int nouveau_flip_complete(void *chan);
79struct nv84_fence_chan { 79struct nv84_fence_chan {
80 struct nouveau_fence_chan base; 80 struct nouveau_fence_chan base;
81 struct nouveau_vma vma; 81 struct nouveau_vma vma;
82 struct nouveau_vma vma_gart;
82 struct nouveau_vma dispc_vma[4]; 83 struct nouveau_vma dispc_vma[4];
83}; 84};
84 85
85struct nv84_fence_priv { 86struct nv84_fence_priv {
86 struct nouveau_fence_priv base; 87 struct nouveau_fence_priv base;
87 struct nouveau_bo *bo; 88 struct nouveau_bo *bo;
89 struct nouveau_bo *bo_gart;
88 u32 *suspend; 90 u32 *suspend;
89}; 91};
90 92
91u64 nv84_fence_crtc(struct nouveau_channel *, int); 93u64 nv84_fence_crtc(struct nouveau_channel *, int);
92int nv84_fence_emit(struct nouveau_fence *);
93int nv84_fence_sync(struct nouveau_fence *, struct nouveau_channel *,
94 struct nouveau_channel *);
95u32 nv84_fence_read(struct nouveau_channel *);
96int nv84_fence_context_new(struct nouveau_channel *); 94int nv84_fence_context_new(struct nouveau_channel *);
97void nv84_fence_context_del(struct nouveau_channel *);
98bool nv84_fence_suspend(struct nouveau_drm *);
99void nv84_fence_resume(struct nouveau_drm *);
100void nv84_fence_destroy(struct nouveau_drm *);
101 95
102#endif 96#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 706113880622..6c45ddb9ebe9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -787,7 +787,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
787 } 787 }
788 } 788 }
789 789
790 ret = nouveau_fence_new(chan, &fence); 790 ret = nouveau_fence_new(chan, false, &fence);
791 if (ret) { 791 if (ret) {
792 NV_ERROR(cli, "error fencing pushbuf: %d\n", ret); 792 NV_ERROR(cli, "error fencing pushbuf: %d\n", ret);
793 WIND_RING(chan); 793 WIND_RING(chan);
diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c
index bc6493c1a1ef..9fd475c89820 100644
--- a/drivers/gpu/drm/nouveau/nv84_fence.c
+++ b/drivers/gpu/drm/nouveau/nv84_fence.c
@@ -76,27 +76,39 @@ nv84_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence)
76 return ret; 76 return ret;
77} 77}
78 78
79int 79static int
80nv84_fence_emit(struct nouveau_fence *fence) 80nv84_fence_emit(struct nouveau_fence *fence)
81{ 81{
82 struct nouveau_channel *chan = fence->channel; 82 struct nouveau_channel *chan = fence->channel;
83 struct nv84_fence_chan *fctx = chan->fence; 83 struct nv84_fence_chan *fctx = chan->fence;
84 struct nouveau_fifo_chan *fifo = (void *)chan->object; 84 struct nouveau_fifo_chan *fifo = (void *)chan->object;
85 u64 addr = fctx->vma.offset + fifo->chid * 16; 85 u64 addr = fifo->chid * 16;
86
87 if (fence->sysmem)
88 addr += fctx->vma_gart.offset;
89 else
90 addr += fctx->vma.offset;
91
86 return fctx->base.emit32(chan, addr, fence->sequence); 92 return fctx->base.emit32(chan, addr, fence->sequence);
87} 93}
88 94
89int 95static int
90nv84_fence_sync(struct nouveau_fence *fence, 96nv84_fence_sync(struct nouveau_fence *fence,
91 struct nouveau_channel *prev, struct nouveau_channel *chan) 97 struct nouveau_channel *prev, struct nouveau_channel *chan)
92{ 98{
93 struct nv84_fence_chan *fctx = chan->fence; 99 struct nv84_fence_chan *fctx = chan->fence;
94 struct nouveau_fifo_chan *fifo = (void *)prev->object; 100 struct nouveau_fifo_chan *fifo = (void *)prev->object;
95 u64 addr = fctx->vma.offset + fifo->chid * 16; 101 u64 addr = fifo->chid * 16;
102
103 if (fence->sysmem)
104 addr += fctx->vma_gart.offset;
105 else
106 addr += fctx->vma.offset;
107
96 return fctx->base.sync32(chan, addr, fence->sequence); 108 return fctx->base.sync32(chan, addr, fence->sequence);
97} 109}
98 110
99u32 111static u32
100nv84_fence_read(struct nouveau_channel *chan) 112nv84_fence_read(struct nouveau_channel *chan)
101{ 113{
102 struct nouveau_fifo_chan *fifo = (void *)chan->object; 114 struct nouveau_fifo_chan *fifo = (void *)chan->object;
@@ -104,7 +116,7 @@ nv84_fence_read(struct nouveau_channel *chan)
104 return nouveau_bo_rd32(priv->bo, fifo->chid * 16/4); 116 return nouveau_bo_rd32(priv->bo, fifo->chid * 16/4);
105} 117}
106 118
107void 119static void
108nv84_fence_context_del(struct nouveau_channel *chan) 120nv84_fence_context_del(struct nouveau_channel *chan)
109{ 121{
110 struct drm_device *dev = chan->drm->dev; 122 struct drm_device *dev = chan->drm->dev;
@@ -117,6 +129,7 @@ nv84_fence_context_del(struct nouveau_channel *chan)
117 nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); 129 nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]);
118 } 130 }
119 131
132 nouveau_bo_vma_del(priv->bo, &fctx->vma_gart);
120 nouveau_bo_vma_del(priv->bo, &fctx->vma); 133 nouveau_bo_vma_del(priv->bo, &fctx->vma);
121 nouveau_fence_context_del(&fctx->base); 134 nouveau_fence_context_del(&fctx->base);
122 chan->fence = NULL; 135 chan->fence = NULL;
@@ -144,8 +157,10 @@ nv84_fence_context_new(struct nouveau_channel *chan)
144 fctx->base.sync32 = nv84_fence_sync32; 157 fctx->base.sync32 = nv84_fence_sync32;
145 158
146 ret = nouveau_bo_vma_add(priv->bo, client->vm, &fctx->vma); 159 ret = nouveau_bo_vma_add(priv->bo, client->vm, &fctx->vma);
147 if (ret) 160 if (ret == 0) {
148 nv84_fence_context_del(chan); 161 ret = nouveau_bo_vma_add(priv->bo_gart, client->vm,
162 &fctx->vma_gart);
163 }
149 164
150 /* map display semaphore buffers into channel's vm */ 165 /* map display semaphore buffers into channel's vm */
151 for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { 166 for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) {
@@ -154,10 +169,13 @@ nv84_fence_context_new(struct nouveau_channel *chan)
154 } 169 }
155 170
156 nouveau_bo_wr32(priv->bo, fifo->chid * 16/4, 0x00000000); 171 nouveau_bo_wr32(priv->bo, fifo->chid * 16/4, 0x00000000);
172
173 if (ret)
174 nv84_fence_context_del(chan);
157 return ret; 175 return ret;
158} 176}
159 177
160bool 178static bool
161nv84_fence_suspend(struct nouveau_drm *drm) 179nv84_fence_suspend(struct nouveau_drm *drm)
162{ 180{
163 struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); 181 struct nouveau_fifo *pfifo = nouveau_fifo(drm->device);
@@ -173,7 +191,7 @@ nv84_fence_suspend(struct nouveau_drm *drm)
173 return priv->suspend != NULL; 191 return priv->suspend != NULL;
174} 192}
175 193
176void 194static void
177nv84_fence_resume(struct nouveau_drm *drm) 195nv84_fence_resume(struct nouveau_drm *drm)
178{ 196{
179 struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); 197 struct nouveau_fifo *pfifo = nouveau_fifo(drm->device);
@@ -188,10 +206,14 @@ nv84_fence_resume(struct nouveau_drm *drm)
188 } 206 }
189} 207}
190 208
191void 209static void
192nv84_fence_destroy(struct nouveau_drm *drm) 210nv84_fence_destroy(struct nouveau_drm *drm)
193{ 211{
194 struct nv84_fence_priv *priv = drm->fence; 212 struct nv84_fence_priv *priv = drm->fence;
213 nouveau_bo_unmap(priv->bo_gart);
214 if (priv->bo_gart)
215 nouveau_bo_unpin(priv->bo_gart);
216 nouveau_bo_ref(NULL, &priv->bo_gart);
195 nouveau_bo_unmap(priv->bo); 217 nouveau_bo_unmap(priv->bo);
196 if (priv->bo) 218 if (priv->bo)
197 nouveau_bo_unpin(priv->bo); 219 nouveau_bo_unpin(priv->bo);
@@ -233,6 +255,21 @@ nv84_fence_create(struct nouveau_drm *drm)
233 nouveau_bo_ref(NULL, &priv->bo); 255 nouveau_bo_ref(NULL, &priv->bo);
234 } 256 }
235 257
258 if (ret == 0)
259 ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0,
260 TTM_PL_FLAG_TT, 0, 0, NULL,
261 &priv->bo_gart);
262 if (ret == 0) {
263 ret = nouveau_bo_pin(priv->bo_gart, TTM_PL_FLAG_TT);
264 if (ret == 0) {
265 ret = nouveau_bo_map(priv->bo_gart);
266 if (ret)
267 nouveau_bo_unpin(priv->bo_gart);
268 }
269 if (ret)
270 nouveau_bo_ref(NULL, &priv->bo_gart);
271 }
272
236 if (ret) 273 if (ret)
237 nv84_fence_destroy(drm); 274 nv84_fence_destroy(drm);
238 return ret; 275 return ret;
diff --git a/drivers/gpu/drm/nouveau/nvc0_fence.c b/drivers/gpu/drm/nouveau/nvc0_fence.c
index b7def390d808..9566267fbc42 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fence.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fence.c
@@ -81,37 +81,10 @@ nvc0_fence_context_new(struct nouveau_channel *chan)
81int 81int
82nvc0_fence_create(struct nouveau_drm *drm) 82nvc0_fence_create(struct nouveau_drm *drm)
83{ 83{
84 struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); 84 int ret = nv84_fence_create(drm);
85 struct nv84_fence_priv *priv;
86 int ret;
87
88 priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL);
89 if (!priv)
90 return -ENOMEM;
91
92 priv->base.dtor = nv84_fence_destroy;
93 priv->base.suspend = nv84_fence_suspend;
94 priv->base.resume = nv84_fence_resume;
95 priv->base.context_new = nvc0_fence_context_new;
96 priv->base.context_del = nv84_fence_context_del;
97
98 init_waitqueue_head(&priv->base.waiting);
99 priv->base.uevent = true;
100
101 ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0,
102 TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo);
103 if (ret == 0) { 85 if (ret == 0) {
104 ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); 86 struct nv84_fence_priv *priv = drm->fence;
105 if (ret == 0) { 87 priv->base.context_new = nvc0_fence_context_new;
106 ret = nouveau_bo_map(priv->bo);
107 if (ret)
108 nouveau_bo_unpin(priv->bo);
109 }
110 if (ret)
111 nouveau_bo_ref(NULL, &priv->bo);
112 } 88 }
113
114 if (ret)
115 nv84_fence_destroy(drm);
116 return ret; 89 return ret;
117} 90}