diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_channel.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_channel.c | 49 |
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 */ |