aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2011-06-17 09:41:54 -0400
committerBen Skeggs <bskeggs@redhat.com>2011-06-18 00:56:24 -0400
commitb16a5a18ff994532120c1d18e678bbc5fb477b62 (patch)
treef8d8e69abbeba8ae0f7221462106038bebf6b5eb /drivers
parentf66b3d5540994cb92182312be24944864cec5a16 (diff)
drm/nouveau: fix assumption that semaphore dmaobj is valid in x-chan sync
The DDX modifies DMA_SEMAPHORE on nv50 in order to implement sync-to-vblank, things will go very wrong for cross-channel sync after this. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c59
1 files changed, 25 insertions, 34 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index 4b9f4493c9f9..7347075ca5b8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -339,11 +339,12 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
339 int ret; 339 int ret;
340 340
341 if (dev_priv->chipset < 0x84) { 341 if (dev_priv->chipset < 0x84) {
342 ret = RING_SPACE(chan, 3); 342 ret = RING_SPACE(chan, 4);
343 if (ret) 343 if (ret)
344 return ret; 344 return ret;
345 345
346 BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 2); 346 BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 3);
347 OUT_RING (chan, NvSema);
347 OUT_RING (chan, sema->mem->start); 348 OUT_RING (chan, sema->mem->start);
348 OUT_RING (chan, 1); 349 OUT_RING (chan, 1);
349 } else 350 } else
@@ -351,10 +352,12 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
351 struct nouveau_vma *vma = &dev_priv->fence.bo->vma; 352 struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
352 u64 offset = vma->offset + sema->mem->start; 353 u64 offset = vma->offset + sema->mem->start;
353 354
354 ret = RING_SPACE(chan, 5); 355 ret = RING_SPACE(chan, 7);
355 if (ret) 356 if (ret)
356 return ret; 357 return ret;
357 358
359 BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
360 OUT_RING (chan, chan->vram_handle);
358 BEGIN_RING(chan, NvSubSw, 0x0010, 4); 361 BEGIN_RING(chan, NvSubSw, 0x0010, 4);
359 OUT_RING (chan, upper_32_bits(offset)); 362 OUT_RING (chan, upper_32_bits(offset));
360 OUT_RING (chan, lower_32_bits(offset)); 363 OUT_RING (chan, lower_32_bits(offset));
@@ -394,11 +397,12 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
394 int ret; 397 int ret;
395 398
396 if (dev_priv->chipset < 0x84) { 399 if (dev_priv->chipset < 0x84) {
397 ret = RING_SPACE(chan, 4); 400 ret = RING_SPACE(chan, 5);
398 if (ret) 401 if (ret)
399 return ret; 402 return ret;
400 403
401 BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1); 404 BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 2);
405 OUT_RING (chan, NvSema);
402 OUT_RING (chan, sema->mem->start); 406 OUT_RING (chan, sema->mem->start);
403 BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1); 407 BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1);
404 OUT_RING (chan, 1); 408 OUT_RING (chan, 1);
@@ -407,10 +411,12 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
407 struct nouveau_vma *vma = &dev_priv->fence.bo->vma; 411 struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
408 u64 offset = vma->offset + sema->mem->start; 412 u64 offset = vma->offset + sema->mem->start;
409 413
410 ret = RING_SPACE(chan, 5); 414 ret = RING_SPACE(chan, 7);
411 if (ret) 415 if (ret)
412 return ret; 416 return ret;
413 417
418 BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
419 OUT_RING (chan, chan->vram_handle);
414 BEGIN_RING(chan, NvSubSw, 0x0010, 4); 420 BEGIN_RING(chan, NvSubSw, 0x0010, 4);
415 OUT_RING (chan, upper_32_bits(offset)); 421 OUT_RING (chan, upper_32_bits(offset));
416 OUT_RING (chan, lower_32_bits(offset)); 422 OUT_RING (chan, lower_32_bits(offset));
@@ -504,22 +510,22 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
504 struct nouveau_gpuobj *obj = NULL; 510 struct nouveau_gpuobj *obj = NULL;
505 int ret; 511 int ret;
506 512
507 if (dev_priv->card_type >= NV_C0) 513 if (dev_priv->card_type < NV_C0) {
508 goto out_initialised; 514 /* Create an NV_SW object for various sync purposes */
515 ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW);
516 if (ret)
517 return ret;
509 518
510 /* Create an NV_SW object for various sync purposes */ 519 ret = RING_SPACE(chan, 2);
511 ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW); 520 if (ret)
512 if (ret) 521 return ret;
513 return ret;
514 522
515 /* we leave subchannel empty for nvc0 */ 523 BEGIN_RING(chan, NvSubSw, 0, 1);
516 ret = RING_SPACE(chan, 2); 524 OUT_RING (chan, NvSw);
517 if (ret) 525 FIRE_RING (chan);
518 return ret; 526 }
519 BEGIN_RING(chan, NvSubSw, 0, 1);
520 OUT_RING(chan, NvSw);
521 527
522 /* Create a DMA object for the shared cross-channel sync area. */ 528 /* Setup area of memory shared between all channels for x-chan sync */
523 if (USE_SEMA(dev) && dev_priv->chipset < 0x84) { 529 if (USE_SEMA(dev) && dev_priv->chipset < 0x84) {
524 struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem; 530 struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem;
525 531
@@ -534,23 +540,8 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
534 nouveau_gpuobj_ref(NULL, &obj); 540 nouveau_gpuobj_ref(NULL, &obj);
535 if (ret) 541 if (ret)
536 return ret; 542 return ret;
537
538 ret = RING_SPACE(chan, 2);
539 if (ret)
540 return ret;
541 BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
542 OUT_RING(chan, NvSema);
543 } else {
544 ret = RING_SPACE(chan, 2);
545 if (ret)
546 return ret;
547 BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
548 OUT_RING (chan, chan->vram_handle); /* whole VM */
549 } 543 }
550 544
551 FIRE_RING(chan);
552
553out_initialised:
554 INIT_LIST_HEAD(&chan->fence.pending); 545 INIT_LIST_HEAD(&chan->fence.pending);
555 spin_lock_init(&chan->fence.lock); 546 spin_lock_init(&chan->fence.lock);
556 atomic_set(&chan->fence.last_sequence_irq, 0); 547 atomic_set(&chan->fence.last_sequence_irq, 0);