aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_channel.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_channel.c49
1 files changed, 27 insertions, 22 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c
index 694f6325311a..d25dc249535b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_channel.c
+++ b/drivers/gpu/drm/nouveau/nouveau_channel.c
@@ -119,6 +119,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
119 struct drm_file *file_priv, 119 struct drm_file *file_priv,
120 uint32_t vram_handle, uint32_t gart_handle) 120 uint32_t vram_handle, uint32_t gart_handle)
121{ 121{
122 struct nouveau_exec_engine *fence = nv_engine(dev, NVOBJ_ENGINE_FENCE);
122 struct drm_nouveau_private *dev_priv = dev->dev_private; 123 struct drm_nouveau_private *dev_priv = dev->dev_private;
123 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 124 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
124 struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); 125 struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
@@ -157,8 +158,6 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
157 } 158 }
158 159
159 NV_DEBUG(dev, "initialising channel %d\n", chan->id); 160 NV_DEBUG(dev, "initialising channel %d\n", chan->id);
160 INIT_LIST_HEAD(&chan->fence.pending);
161 spin_lock_init(&chan->fence.lock);
162 161
163 /* setup channel's memory and vm */ 162 /* setup channel's memory and vm */
164 ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle); 163 ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
@@ -188,7 +187,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
188 chan->user_put = 0x40; 187 chan->user_put = 0x40;
189 chan->user_get = 0x44; 188 chan->user_get = 0x44;
190 if (dev_priv->card_type >= NV_50) 189 if (dev_priv->card_type >= NV_50)
191 chan->user_get_hi = 0x60; 190 chan->user_get_hi = 0x60;
192 191
193 /* disable the fifo caches */ 192 /* disable the fifo caches */
194 pfifo->reassign(dev, false); 193 pfifo->reassign(dev, false);
@@ -211,7 +210,6 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
211 210
212 for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) 211 for (i = 0; i < NOUVEAU_DMA_SKIPS; i++)
213 OUT_RING (chan, 0x00000000); 212 OUT_RING (chan, 0x00000000);
214 FIRE_RING(chan);
215 213
216 ret = nouveau_gpuobj_gr_new(chan, NvSw, nouveau_software_class(dev)); 214 ret = nouveau_gpuobj_gr_new(chan, NvSw, nouveau_software_class(dev));
217 if (ret) { 215 if (ret) {
@@ -219,7 +217,21 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
219 return ret; 217 return ret;
220 } 218 }
221 219
222 ret = nouveau_fence_channel_init(chan); 220 if (dev_priv->card_type < NV_C0) {
221 ret = RING_SPACE(chan, 2);
222 if (ret) {
223 nouveau_channel_put(&chan);
224 return ret;
225 }
226
227 BEGIN_NV04(chan, NvSubSw, NV01_SUBCHAN_OBJECT, 1);
228 OUT_RING (chan, NvSw);
229 FIRE_RING (chan);
230 }
231
232 FIRE_RING(chan);
233
234 ret = fence->context_new(chan, NVOBJ_ENGINE_FENCE);
223 if (ret) { 235 if (ret) {
224 nouveau_channel_put(&chan); 236 nouveau_channel_put(&chan);
225 return ret; 237 return ret;
@@ -291,12 +303,6 @@ nouveau_channel_put_unlocked(struct nouveau_channel **pchan)
291 /* give it chance to idle */ 303 /* give it chance to idle */
292 nouveau_channel_idle(chan); 304 nouveau_channel_idle(chan);
293 305
294 /* ensure all outstanding fences are signaled. they should be if the
295 * above attempts at idling were OK, but if we failed this'll tell TTM
296 * we're done with the buffers.
297 */
298 nouveau_fence_channel_fini(chan);
299
300 /* boot it off the hardware */ 306 /* boot it off the hardware */
301 pfifo->reassign(dev, false); 307 pfifo->reassign(dev, false);
302 308
@@ -305,6 +311,9 @@ nouveau_channel_put_unlocked(struct nouveau_channel **pchan)
305 for (i = 0; i < NVOBJ_ENGINE_NR; i++) { 311 for (i = 0; i < NVOBJ_ENGINE_NR; i++) {
306 if (chan->engctx[i]) 312 if (chan->engctx[i])
307 dev_priv->eng[i]->context_del(chan, i); 313 dev_priv->eng[i]->context_del(chan, i);
314 /*XXX: clean this up later, order is important */
315 if (i == NVOBJ_ENGINE_FENCE)
316 pfifo->destroy_context(chan);
308 } 317 }
309 318
310 pfifo->reassign(dev, true); 319 pfifo->reassign(dev, true);
@@ -367,18 +376,14 @@ nouveau_channel_idle(struct nouveau_channel *chan)
367 struct nouveau_fence *fence = NULL; 376 struct nouveau_fence *fence = NULL;
368 int ret; 377 int ret;
369 378
370 nouveau_fence_update(chan); 379 ret = nouveau_fence_new(chan, &fence);
371 380 if (!ret) {
372 if (chan->fence.sequence != chan->fence.sequence_ack) { 381 ret = nouveau_fence_wait(fence, false, false);
373 ret = nouveau_fence_new(chan, &fence); 382 nouveau_fence_unref(&fence);
374 if (!ret) {
375 ret = nouveau_fence_wait(fence, false, false);
376 nouveau_fence_unref(&fence);
377 }
378
379 if (ret)
380 NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id);
381 } 383 }
384
385 if (ret)
386 NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id);
382} 387}
383 388
384/* cleans up all the fifos from file_priv */ 389/* cleans up all the fifos from file_priv */