aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_gem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_gem.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c55
1 files changed, 32 insertions, 23 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 18fd8ac9fca7..70cc30803e3b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -220,7 +220,6 @@ nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains,
220} 220}
221 221
222struct validate_op { 222struct validate_op {
223 struct nouveau_fence *fence;
224 struct list_head vram_list; 223 struct list_head vram_list;
225 struct list_head gart_list; 224 struct list_head gart_list;
226 struct list_head both_list; 225 struct list_head both_list;
@@ -252,17 +251,11 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence)
252} 251}
253 252
254static void 253static void
255validate_fini(struct validate_op *op, bool success) 254validate_fini(struct validate_op *op, struct nouveau_fence* fence)
256{ 255{
257 struct nouveau_fence *fence = op->fence; 256 validate_fini_list(&op->vram_list, fence);
258 257 validate_fini_list(&op->gart_list, fence);
259 if (unlikely(!success)) 258 validate_fini_list(&op->both_list, fence);
260 op->fence = NULL;
261
262 validate_fini_list(&op->vram_list, op->fence);
263 validate_fini_list(&op->gart_list, op->fence);
264 validate_fini_list(&op->both_list, op->fence);
265 nouveau_fence_unref((void *)&fence);
266} 259}
267 260
268static int 261static int
@@ -328,6 +321,7 @@ retry:
328 else { 321 else {
329 NV_ERROR(dev, "invalid valid domains: 0x%08x\n", 322 NV_ERROR(dev, "invalid valid domains: 0x%08x\n",
330 b->valid_domains); 323 b->valid_domains);
324 list_add_tail(&nvbo->entry, &op->both_list);
331 validate_fini(op, NULL); 325 validate_fini(op, NULL);
332 return -EINVAL; 326 return -EINVAL;
333 } 327 }
@@ -420,10 +414,6 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
420 INIT_LIST_HEAD(&op->gart_list); 414 INIT_LIST_HEAD(&op->gart_list);
421 INIT_LIST_HEAD(&op->both_list); 415 INIT_LIST_HEAD(&op->both_list);
422 416
423 ret = nouveau_fence_new(chan, &op->fence, false);
424 if (ret)
425 return ret;
426
427 if (nr_buffers == 0) 417 if (nr_buffers == 0)
428 return 0; 418 return 0;
429 419
@@ -477,13 +467,14 @@ u_memcpya(uint64_t user, unsigned nmemb, unsigned size)
477static int 467static int
478nouveau_gem_pushbuf_reloc_apply(struct nouveau_channel *chan, int nr_bo, 468nouveau_gem_pushbuf_reloc_apply(struct nouveau_channel *chan, int nr_bo,
479 struct drm_nouveau_gem_pushbuf_bo *bo, 469 struct drm_nouveau_gem_pushbuf_bo *bo,
480 int nr_relocs, uint64_t ptr_relocs, 470 unsigned nr_relocs, uint64_t ptr_relocs,
481 int nr_dwords, int first_dword, 471 unsigned nr_dwords, unsigned first_dword,
482 uint32_t *pushbuf, bool is_iomem) 472 uint32_t *pushbuf, bool is_iomem)
483{ 473{
484 struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL; 474 struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL;
485 struct drm_device *dev = chan->dev; 475 struct drm_device *dev = chan->dev;
486 int ret = 0, i; 476 int ret = 0;
477 unsigned i;
487 478
488 reloc = u_memcpya(ptr_relocs, nr_relocs, sizeof(*reloc)); 479 reloc = u_memcpya(ptr_relocs, nr_relocs, sizeof(*reloc));
489 if (IS_ERR(reloc)) 480 if (IS_ERR(reloc))
@@ -541,6 +532,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
541 struct drm_nouveau_gem_pushbuf_bo *bo = NULL; 532 struct drm_nouveau_gem_pushbuf_bo *bo = NULL;
542 struct nouveau_channel *chan; 533 struct nouveau_channel *chan;
543 struct validate_op op; 534 struct validate_op op;
535 struct nouveau_fence* fence = 0;
544 uint32_t *pushbuf = NULL; 536 uint32_t *pushbuf = NULL;
545 int ret = 0, do_reloc = 0, i; 537 int ret = 0, do_reloc = 0, i;
546 538
@@ -597,7 +589,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
597 589
598 OUT_RINGp(chan, pushbuf, req->nr_dwords); 590 OUT_RINGp(chan, pushbuf, req->nr_dwords);
599 591
600 ret = nouveau_fence_emit(op.fence); 592 ret = nouveau_fence_new(chan, &fence, true);
601 if (ret) { 593 if (ret) {
602 NV_ERROR(dev, "error fencing pushbuf: %d\n", ret); 594 NV_ERROR(dev, "error fencing pushbuf: %d\n", ret);
603 WIND_RING(chan); 595 WIND_RING(chan);
@@ -605,7 +597,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
605 } 597 }
606 598
607 if (nouveau_gem_pushbuf_sync(chan)) { 599 if (nouveau_gem_pushbuf_sync(chan)) {
608 ret = nouveau_fence_wait(op.fence, NULL, false, false); 600 ret = nouveau_fence_wait(fence, NULL, false, false);
609 if (ret) { 601 if (ret) {
610 for (i = 0; i < req->nr_dwords; i++) 602 for (i = 0; i < req->nr_dwords; i++)
611 NV_ERROR(dev, "0x%08x\n", pushbuf[i]); 603 NV_ERROR(dev, "0x%08x\n", pushbuf[i]);
@@ -614,7 +606,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
614 } 606 }
615 607
616out: 608out:
617 validate_fini(&op, ret == 0); 609 validate_fini(&op, fence);
610 nouveau_fence_unref((void**)&fence);
618 mutex_unlock(&dev->struct_mutex); 611 mutex_unlock(&dev->struct_mutex);
619 kfree(pushbuf); 612 kfree(pushbuf);
620 kfree(bo); 613 kfree(bo);
@@ -634,6 +627,7 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
634 struct drm_gem_object *gem; 627 struct drm_gem_object *gem;
635 struct nouveau_bo *pbbo; 628 struct nouveau_bo *pbbo;
636 struct validate_op op; 629 struct validate_op op;
630 struct nouveau_fence* fence = 0;
637 int i, ret = 0, do_reloc = 0; 631 int i, ret = 0, do_reloc = 0;
638 632
639 NOUVEAU_CHECK_INITIALISED_WITH_RETURN; 633 NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
@@ -675,6 +669,18 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
675 } 669 }
676 pbbo = nouveau_gem_object(gem); 670 pbbo = nouveau_gem_object(gem);
677 671
672 if ((req->offset & 3) || req->nr_dwords < 2 ||
673 (unsigned long)req->offset > (unsigned long)pbbo->bo.mem.size ||
674 (unsigned long)req->nr_dwords >
675 ((unsigned long)(pbbo->bo.mem.size - req->offset ) >> 2)) {
676 NV_ERROR(dev, "pb call misaligned or out of bounds: "
677 "%d + %d * 4 > %ld\n",
678 req->offset, req->nr_dwords, pbbo->bo.mem.size);
679 ret = -EINVAL;
680 drm_gem_object_unreference(gem);
681 goto out;
682 }
683
678 ret = ttm_bo_reserve(&pbbo->bo, false, false, true, 684 ret = ttm_bo_reserve(&pbbo->bo, false, false, true,
679 chan->fence.sequence); 685 chan->fence.sequence);
680 if (ret) { 686 if (ret) {
@@ -772,7 +778,7 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
772 OUT_RING(chan, 0); 778 OUT_RING(chan, 0);
773 } 779 }
774 780
775 ret = nouveau_fence_emit(op.fence); 781 ret = nouveau_fence_new(chan, &fence, true);
776 if (ret) { 782 if (ret) {
777 NV_ERROR(dev, "error fencing pushbuf: %d\n", ret); 783 NV_ERROR(dev, "error fencing pushbuf: %d\n", ret);
778 WIND_RING(chan); 784 WIND_RING(chan);
@@ -780,7 +786,8 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
780 } 786 }
781 787
782out: 788out:
783 validate_fini(&op, ret == 0); 789 validate_fini(&op, fence);
790 nouveau_fence_unref((void**)&fence);
784 mutex_unlock(&dev->struct_mutex); 791 mutex_unlock(&dev->struct_mutex);
785 kfree(bo); 792 kfree(bo);
786 793
@@ -918,7 +925,9 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
918 } 925 }
919 926
920 if (req->flags & NOUVEAU_GEM_CPU_PREP_NOBLOCK) { 927 if (req->flags & NOUVEAU_GEM_CPU_PREP_NOBLOCK) {
928 spin_lock(&nvbo->bo.lock);
921 ret = ttm_bo_wait(&nvbo->bo, false, false, no_wait); 929 ret = ttm_bo_wait(&nvbo->bo, false, false, no_wait);
930 spin_unlock(&nvbo->bo.lock);
922 } else { 931 } else {
923 ret = ttm_bo_synccpu_write_grab(&nvbo->bo, no_wait); 932 ret = ttm_bo_synccpu_write_grab(&nvbo->bo, no_wait);
924 if (ret == 0) 933 if (ret == 0)