diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_gem.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_gem.c | 55 |
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 | ||
222 | struct validate_op { | 222 | struct 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 | ||
254 | static void | 253 | static void |
255 | validate_fini(struct validate_op *op, bool success) | 254 | validate_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 | ||
268 | static int | 261 | static 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) | |||
477 | static int | 467 | static int |
478 | nouveau_gem_pushbuf_reloc_apply(struct nouveau_channel *chan, int nr_bo, | 468 | nouveau_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 | ||
616 | out: | 608 | out: |
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 | ||
782 | out: | 788 | out: |
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) |