aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Olšák <maraeo@gmail.com>2011-08-13 16:32:11 -0400
committerDave Airlie <airlied@redhat.com>2011-08-31 14:25:35 -0400
commitdfadbbdb57b3f2bb33e14f129a43047c6f0caefa (patch)
tree0a6e00b5fa56d9f5a5b4dc833e3057e4660efd1c
parentb464e9a25c27884eb8ee2c2bb904ec50bd3990ea (diff)
drm/ttm: add a way to bo_wait for either the last read or last write
Sometimes we want to know whether a buffer is busy and wait for it (bo_wait). However, sometimes it would be more useful to be able to query whether a buffer is busy and being either read or written, and wait until it's stopped being either read or written. The point of this is to be able to avoid unnecessary waiting, e.g. if a GPU has written something to a buffer and is now reading that buffer, and a CPU wants to map that buffer for read, it needs to only wait for the last write. If there were no write, there wouldn't be any waiting needed. This, or course, requires user space drivers to send read/write flags with each relocation (like we have read/write domains in radeon, so we can actually use those for something useful now). Now how this patch works: The read/write flags should passed to ttm_validate_buffer. TTM maintains separate sync objects of the last read and write for each buffer, in addition to the sync object of the last use of a buffer. ttm_bo_wait then operates with one the sync objects. Signed-off-by: Marek Olšák <maraeo@gmail.com> Reviewed-by: Jerome Glisse <jglisse@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c5
-rw-r--r--drivers/gpu/drm/radeon/radeon_cs.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.h2
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c97
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_util.c26
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_vm.c2
-rw-r--r--drivers/gpu/drm/ttm/ttm_execbuf_util.c19
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c1
-rw-r--r--include/drm/ttm/ttm_bo_api.h16
-rw-r--r--include/drm/ttm/ttm_execbuf_util.h6
11 files changed, 139 insertions, 39 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 890d50e4d682..e87e24b9c0af 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -1104,7 +1104,8 @@ nouveau_bo_vma_del(struct nouveau_bo *nvbo, struct nouveau_vma *vma)
1104 if (vma->node) { 1104 if (vma->node) {
1105 if (nvbo->bo.mem.mem_type != TTM_PL_SYSTEM) { 1105 if (nvbo->bo.mem.mem_type != TTM_PL_SYSTEM) {
1106 spin_lock(&nvbo->bo.bdev->fence_lock); 1106 spin_lock(&nvbo->bo.bdev->fence_lock);
1107 ttm_bo_wait(&nvbo->bo, false, false, false); 1107 ttm_bo_wait(&nvbo->bo, false, false, false,
1108 TTM_USAGE_READWRITE);
1108 spin_unlock(&nvbo->bo.bdev->fence_lock); 1109 spin_unlock(&nvbo->bo.bdev->fence_lock);
1109 nouveau_vm_unmap(vma); 1110 nouveau_vm_unmap(vma);
1110 } 1111 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 5f0bc57fdaab..322bf62a0645 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -589,7 +589,8 @@ nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev,
589 } 589 }
590 590
591 spin_lock(&nvbo->bo.bdev->fence_lock); 591 spin_lock(&nvbo->bo.bdev->fence_lock);
592 ret = ttm_bo_wait(&nvbo->bo, false, false, false); 592 ret = ttm_bo_wait(&nvbo->bo, false, false, false,
593 TTM_USAGE_READWRITE);
593 spin_unlock(&nvbo->bo.bdev->fence_lock); 594 spin_unlock(&nvbo->bo.bdev->fence_lock);
594 if (ret) { 595 if (ret) {
595 NV_ERROR(dev, "reloc wait_idle failed: %d\n", ret); 596 NV_ERROR(dev, "reloc wait_idle failed: %d\n", ret);
@@ -825,7 +826,7 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
825 nvbo = nouveau_gem_object(gem); 826 nvbo = nouveau_gem_object(gem);
826 827
827 spin_lock(&nvbo->bo.bdev->fence_lock); 828 spin_lock(&nvbo->bo.bdev->fence_lock);
828 ret = ttm_bo_wait(&nvbo->bo, true, true, no_wait); 829 ret = ttm_bo_wait(&nvbo->bo, true, true, no_wait, TTM_USAGE_READWRITE);
829 spin_unlock(&nvbo->bo.bdev->fence_lock); 830 spin_unlock(&nvbo->bo.bdev->fence_lock);
830 drm_gem_object_unreference_unlocked(gem); 831 drm_gem_object_unreference_unlocked(gem);
831 return ret; 832 return ret;
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index fae00c0d75aa..14e853151105 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -80,6 +80,7 @@ int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
80 p->relocs[i].lobj.wdomain = r->write_domain; 80 p->relocs[i].lobj.wdomain = r->write_domain;
81 p->relocs[i].lobj.rdomain = r->read_domains; 81 p->relocs[i].lobj.rdomain = r->read_domains;
82 p->relocs[i].lobj.tv.bo = &p->relocs[i].robj->tbo; 82 p->relocs[i].lobj.tv.bo = &p->relocs[i].robj->tbo;
83 p->relocs[i].lobj.tv.usage = TTM_USAGE_READWRITE;
83 p->relocs[i].handle = r->handle; 84 p->relocs[i].handle = r->handle;
84 p->relocs[i].flags = r->flags; 85 p->relocs[i].flags = r->flags;
85 radeon_bo_list_add_object(&p->relocs[i].lobj, 86 radeon_bo_list_add_object(&p->relocs[i].lobj,
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h
index ede6c13628f2..e9dc8b249c5f 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -130,7 +130,7 @@ static inline int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type,
130 if (mem_type) 130 if (mem_type)
131 *mem_type = bo->tbo.mem.mem_type; 131 *mem_type = bo->tbo.mem.mem_type;
132 if (bo->tbo.sync_obj) 132 if (bo->tbo.sync_obj)
133 r = ttm_bo_wait(&bo->tbo, true, true, no_wait); 133 r = ttm_bo_wait(&bo->tbo, true, true, no_wait, TTM_USAGE_READWRITE);
134 spin_unlock(&bo->tbo.bdev->fence_lock); 134 spin_unlock(&bo->tbo.bdev->fence_lock);
135 ttm_bo_unreserve(&bo->tbo); 135 ttm_bo_unreserve(&bo->tbo);
136 return r; 136 return r;
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index a4d38d85909a..b824d9bdd87c 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -498,7 +498,7 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)
498 int ret; 498 int ret;
499 499
500 spin_lock(&bdev->fence_lock); 500 spin_lock(&bdev->fence_lock);
501 (void) ttm_bo_wait(bo, false, false, true); 501 (void) ttm_bo_wait(bo, false, false, true, TTM_USAGE_READWRITE);
502 if (!bo->sync_obj) { 502 if (!bo->sync_obj) {
503 503
504 spin_lock(&glob->lru_lock); 504 spin_lock(&glob->lru_lock);
@@ -566,7 +566,8 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,
566 566
567retry: 567retry:
568 spin_lock(&bdev->fence_lock); 568 spin_lock(&bdev->fence_lock);
569 ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu); 569 ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu,
570 TTM_USAGE_READWRITE);
570 spin_unlock(&bdev->fence_lock); 571 spin_unlock(&bdev->fence_lock);
571 572
572 if (unlikely(ret != 0)) 573 if (unlikely(ret != 0))
@@ -725,7 +726,8 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible,
725 int ret = 0; 726 int ret = 0;
726 727
727 spin_lock(&bdev->fence_lock); 728 spin_lock(&bdev->fence_lock);
728 ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu); 729 ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu,
730 TTM_USAGE_READWRITE);
729 spin_unlock(&bdev->fence_lock); 731 spin_unlock(&bdev->fence_lock);
730 732
731 if (unlikely(ret != 0)) { 733 if (unlikely(ret != 0)) {
@@ -1072,7 +1074,8 @@ int ttm_bo_move_buffer(struct ttm_buffer_object *bo,
1072 * instead of doing it here. 1074 * instead of doing it here.
1073 */ 1075 */
1074 spin_lock(&bdev->fence_lock); 1076 spin_lock(&bdev->fence_lock);
1075 ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu); 1077 ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu,
1078 TTM_USAGE_READWRITE);
1076 spin_unlock(&bdev->fence_lock); 1079 spin_unlock(&bdev->fence_lock);
1077 if (ret) 1080 if (ret)
1078 return ret; 1081 return ret;
@@ -1692,34 +1695,83 @@ out_unlock:
1692 return ret; 1695 return ret;
1693} 1696}
1694 1697
1698static void ttm_bo_unref_sync_obj_locked(struct ttm_buffer_object *bo,
1699 void *sync_obj,
1700 void **extra_sync_obj)
1701{
1702 struct ttm_bo_device *bdev = bo->bdev;
1703 struct ttm_bo_driver *driver = bdev->driver;
1704 void *tmp_obj = NULL, *tmp_obj_read = NULL, *tmp_obj_write = NULL;
1705
1706 /* We must unref the sync obj wherever it's ref'd.
1707 * Note that if we unref bo->sync_obj, we can unref both the read
1708 * and write sync objs too, because they can't be newer than
1709 * bo->sync_obj, so they are no longer relevant. */
1710 if (sync_obj == bo->sync_obj ||
1711 sync_obj == bo->sync_obj_read) {
1712 tmp_obj_read = bo->sync_obj_read;
1713 bo->sync_obj_read = NULL;
1714 }
1715 if (sync_obj == bo->sync_obj ||
1716 sync_obj == bo->sync_obj_write) {
1717 tmp_obj_write = bo->sync_obj_write;
1718 bo->sync_obj_write = NULL;
1719 }
1720 if (sync_obj == bo->sync_obj) {
1721 tmp_obj = bo->sync_obj;
1722 bo->sync_obj = NULL;
1723 }
1724
1725 clear_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags);
1726 spin_unlock(&bdev->fence_lock);
1727 if (tmp_obj)
1728 driver->sync_obj_unref(&tmp_obj);
1729 if (tmp_obj_read)
1730 driver->sync_obj_unref(&tmp_obj_read);
1731 if (tmp_obj_write)
1732 driver->sync_obj_unref(&tmp_obj_write);
1733 if (extra_sync_obj)
1734 driver->sync_obj_unref(extra_sync_obj);
1735 spin_lock(&bdev->fence_lock);
1736}
1737
1695int ttm_bo_wait(struct ttm_buffer_object *bo, 1738int ttm_bo_wait(struct ttm_buffer_object *bo,
1696 bool lazy, bool interruptible, bool no_wait) 1739 bool lazy, bool interruptible, bool no_wait,
1740 enum ttm_buffer_usage usage)
1697{ 1741{
1698 struct ttm_bo_driver *driver = bo->bdev->driver; 1742 struct ttm_bo_driver *driver = bo->bdev->driver;
1699 struct ttm_bo_device *bdev = bo->bdev; 1743 struct ttm_bo_device *bdev = bo->bdev;
1700 void *sync_obj; 1744 void *sync_obj;
1701 void *sync_obj_arg; 1745 void *sync_obj_arg;
1702 int ret = 0; 1746 int ret = 0;
1747 void **bo_sync_obj;
1703 1748
1704 if (likely(bo->sync_obj == NULL)) 1749 switch (usage) {
1750 case TTM_USAGE_READ:
1751 bo_sync_obj = &bo->sync_obj_read;
1752 break;
1753 case TTM_USAGE_WRITE:
1754 bo_sync_obj = &bo->sync_obj_write;
1755 break;
1756 case TTM_USAGE_READWRITE:
1757 default:
1758 bo_sync_obj = &bo->sync_obj;
1759 }
1760
1761 if (likely(*bo_sync_obj == NULL))
1705 return 0; 1762 return 0;
1706 1763
1707 while (bo->sync_obj) { 1764 while (*bo_sync_obj) {
1708 1765
1709 if (driver->sync_obj_signaled(bo->sync_obj, bo->sync_obj_arg)) { 1766 if (driver->sync_obj_signaled(*bo_sync_obj, bo->sync_obj_arg)) {
1710 void *tmp_obj = bo->sync_obj; 1767 ttm_bo_unref_sync_obj_locked(bo, *bo_sync_obj, NULL);
1711 bo->sync_obj = NULL;
1712 clear_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags);
1713 spin_unlock(&bdev->fence_lock);
1714 driver->sync_obj_unref(&tmp_obj);
1715 spin_lock(&bdev->fence_lock);
1716 continue; 1768 continue;
1717 } 1769 }
1718 1770
1719 if (no_wait) 1771 if (no_wait)
1720 return -EBUSY; 1772 return -EBUSY;
1721 1773
1722 sync_obj = driver->sync_obj_ref(bo->sync_obj); 1774 sync_obj = driver->sync_obj_ref(*bo_sync_obj);
1723 sync_obj_arg = bo->sync_obj_arg; 1775 sync_obj_arg = bo->sync_obj_arg;
1724 spin_unlock(&bdev->fence_lock); 1776 spin_unlock(&bdev->fence_lock);
1725 ret = driver->sync_obj_wait(sync_obj, sync_obj_arg, 1777 ret = driver->sync_obj_wait(sync_obj, sync_obj_arg,
@@ -1730,16 +1782,9 @@ int ttm_bo_wait(struct ttm_buffer_object *bo,
1730 return ret; 1782 return ret;
1731 } 1783 }
1732 spin_lock(&bdev->fence_lock); 1784 spin_lock(&bdev->fence_lock);
1733 if (likely(bo->sync_obj == sync_obj && 1785 if (likely(*bo_sync_obj == sync_obj &&
1734 bo->sync_obj_arg == sync_obj_arg)) { 1786 bo->sync_obj_arg == sync_obj_arg)) {
1735 void *tmp_obj = bo->sync_obj; 1787 ttm_bo_unref_sync_obj_locked(bo, *bo_sync_obj, &sync_obj);
1736 bo->sync_obj = NULL;
1737 clear_bit(TTM_BO_PRIV_FLAG_MOVING,
1738 &bo->priv_flags);
1739 spin_unlock(&bdev->fence_lock);
1740 driver->sync_obj_unref(&sync_obj);
1741 driver->sync_obj_unref(&tmp_obj);
1742 spin_lock(&bdev->fence_lock);
1743 } else { 1788 } else {
1744 spin_unlock(&bdev->fence_lock); 1789 spin_unlock(&bdev->fence_lock);
1745 driver->sync_obj_unref(&sync_obj); 1790 driver->sync_obj_unref(&sync_obj);
@@ -1763,7 +1808,7 @@ int ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait)
1763 if (unlikely(ret != 0)) 1808 if (unlikely(ret != 0))
1764 return ret; 1809 return ret;
1765 spin_lock(&bdev->fence_lock); 1810 spin_lock(&bdev->fence_lock);
1766 ret = ttm_bo_wait(bo, false, true, no_wait); 1811 ret = ttm_bo_wait(bo, false, true, no_wait, TTM_USAGE_READWRITE);
1767 spin_unlock(&bdev->fence_lock); 1812 spin_unlock(&bdev->fence_lock);
1768 if (likely(ret == 0)) 1813 if (likely(ret == 0))
1769 atomic_inc(&bo->cpu_writers); 1814 atomic_inc(&bo->cpu_writers);
@@ -1837,7 +1882,7 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink)
1837 */ 1882 */
1838 1883
1839 spin_lock(&bo->bdev->fence_lock); 1884 spin_lock(&bo->bdev->fence_lock);
1840 ret = ttm_bo_wait(bo, false, false, false); 1885 ret = ttm_bo_wait(bo, false, false, false, TTM_USAGE_READWRITE);
1841 spin_unlock(&bo->bdev->fence_lock); 1886 spin_unlock(&bo->bdev->fence_lock);
1842 1887
1843 if (unlikely(ret != 0)) 1888 if (unlikely(ret != 0))
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index ae3c6f5dd2b7..6135f58169ce 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -436,6 +436,8 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
436 atomic_set(&fbo->cpu_writers, 0); 436 atomic_set(&fbo->cpu_writers, 0);
437 437
438 fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj); 438 fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj);
439 fbo->sync_obj_read = driver->sync_obj_ref(bo->sync_obj_read);
440 fbo->sync_obj_write = driver->sync_obj_ref(bo->sync_obj_write);
439 kref_init(&fbo->list_kref); 441 kref_init(&fbo->list_kref);
440 kref_init(&fbo->kref); 442 kref_init(&fbo->kref);
441 fbo->destroy = &ttm_transfered_destroy; 443 fbo->destroy = &ttm_transfered_destroy;
@@ -618,20 +620,30 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
618 struct ttm_mem_reg *old_mem = &bo->mem; 620 struct ttm_mem_reg *old_mem = &bo->mem;
619 int ret; 621 int ret;
620 struct ttm_buffer_object *ghost_obj; 622 struct ttm_buffer_object *ghost_obj;
621 void *tmp_obj = NULL; 623 void *tmp_obj = NULL, *tmp_obj_read = NULL, *tmp_obj_write = NULL;
622 624
623 spin_lock(&bdev->fence_lock); 625 spin_lock(&bdev->fence_lock);
624 if (bo->sync_obj) { 626 if (bo->sync_obj)
625 tmp_obj = bo->sync_obj; 627 tmp_obj = bo->sync_obj;
626 bo->sync_obj = NULL; 628 if (bo->sync_obj_read)
627 } 629 tmp_obj_read = bo->sync_obj_read;
630 if (bo->sync_obj_write)
631 tmp_obj_write = bo->sync_obj_write;
632
628 bo->sync_obj = driver->sync_obj_ref(sync_obj); 633 bo->sync_obj = driver->sync_obj_ref(sync_obj);
634 bo->sync_obj_read = driver->sync_obj_ref(sync_obj);
635 bo->sync_obj_write = driver->sync_obj_ref(sync_obj);
629 bo->sync_obj_arg = sync_obj_arg; 636 bo->sync_obj_arg = sync_obj_arg;
630 if (evict) { 637 if (evict) {
631 ret = ttm_bo_wait(bo, false, false, false); 638 ret = ttm_bo_wait(bo, false, false, false,
639 TTM_USAGE_READWRITE);
632 spin_unlock(&bdev->fence_lock); 640 spin_unlock(&bdev->fence_lock);
633 if (tmp_obj) 641 if (tmp_obj)
634 driver->sync_obj_unref(&tmp_obj); 642 driver->sync_obj_unref(&tmp_obj);
643 if (tmp_obj_read)
644 driver->sync_obj_unref(&tmp_obj_read);
645 if (tmp_obj_write)
646 driver->sync_obj_unref(&tmp_obj_write);
635 if (ret) 647 if (ret)
636 return ret; 648 return ret;
637 649
@@ -655,6 +667,10 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
655 spin_unlock(&bdev->fence_lock); 667 spin_unlock(&bdev->fence_lock);
656 if (tmp_obj) 668 if (tmp_obj)
657 driver->sync_obj_unref(&tmp_obj); 669 driver->sync_obj_unref(&tmp_obj);
670 if (tmp_obj_read)
671 driver->sync_obj_unref(&tmp_obj_read);
672 if (tmp_obj_write)
673 driver->sync_obj_unref(&tmp_obj_write);
658 674
659 ret = ttm_buffer_object_transfer(bo, &ghost_obj); 675 ret = ttm_buffer_object_transfer(bo, &ghost_obj);
660 if (ret) 676 if (ret)
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
index 221b924acebe..ff1e26f4b094 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -122,7 +122,7 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
122 122
123 spin_lock(&bdev->fence_lock); 123 spin_lock(&bdev->fence_lock);
124 if (test_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags)) { 124 if (test_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags)) {
125 ret = ttm_bo_wait(bo, false, true, false); 125 ret = ttm_bo_wait(bo, false, true, false, TTM_USAGE_READWRITE);
126 spin_unlock(&bdev->fence_lock); 126 spin_unlock(&bdev->fence_lock);
127 if (unlikely(ret != 0)) { 127 if (unlikely(ret != 0)) {
128 retval = (ret != -ERESTARTSYS) ? 128 retval = (ret != -ERESTARTSYS) ?
diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
index 3832fe10b4df..36d111a88232 100644
--- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c
+++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
@@ -221,8 +221,18 @@ void ttm_eu_fence_buffer_objects(struct list_head *list, void *sync_obj)
221 221
222 list_for_each_entry(entry, list, head) { 222 list_for_each_entry(entry, list, head) {
223 bo = entry->bo; 223 bo = entry->bo;
224 entry->old_sync_obj_read = NULL;
225 entry->old_sync_obj_write = NULL;
224 entry->old_sync_obj = bo->sync_obj; 226 entry->old_sync_obj = bo->sync_obj;
225 bo->sync_obj = driver->sync_obj_ref(sync_obj); 227 bo->sync_obj = driver->sync_obj_ref(sync_obj);
228 if (entry->usage & TTM_USAGE_READ) {
229 entry->old_sync_obj_read = bo->sync_obj_read;
230 bo->sync_obj_read = driver->sync_obj_ref(sync_obj);
231 }
232 if (entry->usage & TTM_USAGE_WRITE) {
233 entry->old_sync_obj_write = bo->sync_obj_write;
234 bo->sync_obj_write = driver->sync_obj_ref(sync_obj);
235 }
226 bo->sync_obj_arg = entry->new_sync_obj_arg; 236 bo->sync_obj_arg = entry->new_sync_obj_arg;
227 ttm_bo_unreserve_locked(bo); 237 ttm_bo_unreserve_locked(bo);
228 entry->reserved = false; 238 entry->reserved = false;
@@ -231,8 +241,15 @@ void ttm_eu_fence_buffer_objects(struct list_head *list, void *sync_obj)
231 spin_unlock(&bdev->fence_lock); 241 spin_unlock(&bdev->fence_lock);
232 242
233 list_for_each_entry(entry, list, head) { 243 list_for_each_entry(entry, list, head) {
234 if (entry->old_sync_obj) 244 if (entry->old_sync_obj) {
235 driver->sync_obj_unref(&entry->old_sync_obj); 245 driver->sync_obj_unref(&entry->old_sync_obj);
246 }
247 if (entry->old_sync_obj_read) {
248 driver->sync_obj_unref(&entry->old_sync_obj_read);
249 }
250 if (entry->old_sync_obj_write) {
251 driver->sync_obj_unref(&entry->old_sync_obj_write);
252 }
236 } 253 }
237} 254}
238EXPORT_SYMBOL(ttm_eu_fence_buffer_objects); 255EXPORT_SYMBOL(ttm_eu_fence_buffer_objects);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 41b95ed6dbcd..8ca3ddb2ebc3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -224,6 +224,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
224 if (unlikely(cur_validate_node == sw_context->cur_val_buf)) { 224 if (unlikely(cur_validate_node == sw_context->cur_val_buf)) {
225 val_buf = &sw_context->val_bufs[cur_validate_node]; 225 val_buf = &sw_context->val_bufs[cur_validate_node];
226 val_buf->bo = ttm_bo_reference(bo); 226 val_buf->bo = ttm_bo_reference(bo);
227 val_buf->usage = TTM_USAGE_READWRITE;
227 val_buf->new_sync_obj_arg = (void *) dev_priv; 228 val_buf->new_sync_obj_arg = (void *) dev_priv;
228 list_add_tail(&val_buf->head, &sw_context->validate_nodes); 229 list_add_tail(&val_buf->head, &sw_context->validate_nodes);
229 ++sw_context->cur_val_buf; 230 ++sw_context->cur_val_buf;
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
index 42e346985186..da957bf3fe44 100644
--- a/include/drm/ttm/ttm_bo_api.h
+++ b/include/drm/ttm/ttm_bo_api.h
@@ -44,6 +44,11 @@ struct ttm_bo_device;
44 44
45struct drm_mm_node; 45struct drm_mm_node;
46 46
47enum ttm_buffer_usage {
48 TTM_USAGE_READ = 1,
49 TTM_USAGE_WRITE = 2,
50 TTM_USAGE_READWRITE = TTM_USAGE_READ | TTM_USAGE_WRITE
51};
47 52
48/** 53/**
49 * struct ttm_placement 54 * struct ttm_placement
@@ -174,7 +179,10 @@ struct ttm_tt;
174 * the bo_device::lru_lock. 179 * the bo_device::lru_lock.
175 * @reserved: Deadlock-free lock used for synchronization state transitions. 180 * @reserved: Deadlock-free lock used for synchronization state transitions.
176 * @sync_obj_arg: Opaque argument to synchronization object function. 181 * @sync_obj_arg: Opaque argument to synchronization object function.
177 * @sync_obj: Pointer to a synchronization object. 182 * @sync_obj: Pointer to a synchronization object of a last read or write,
183 * whichever is later.
184 * @sync_obj_read: Pointer to a synchronization object of a last read.
185 * @sync_obj_write: Pointer to a synchronization object of a last write.
178 * @priv_flags: Flags describing buffer object internal state. 186 * @priv_flags: Flags describing buffer object internal state.
179 * @vm_rb: Rb node for the vm rb tree. 187 * @vm_rb: Rb node for the vm rb tree.
180 * @vm_node: Address space manager node. 188 * @vm_node: Address space manager node.
@@ -258,6 +266,8 @@ struct ttm_buffer_object {
258 266
259 void *sync_obj_arg; 267 void *sync_obj_arg;
260 void *sync_obj; 268 void *sync_obj;
269 void *sync_obj_read;
270 void *sync_obj_write;
261 unsigned long priv_flags; 271 unsigned long priv_flags;
262 272
263 /** 273 /**
@@ -325,6 +335,7 @@ ttm_bo_reference(struct ttm_buffer_object *bo)
325 * @bo: The buffer object. 335 * @bo: The buffer object.
326 * @interruptible: Use interruptible wait. 336 * @interruptible: Use interruptible wait.
327 * @no_wait: Return immediately if buffer is busy. 337 * @no_wait: Return immediately if buffer is busy.
338 * @usage: Whether to wait for the last read and/or the last write.
328 * 339 *
329 * This function must be called with the bo::mutex held, and makes 340 * This function must be called with the bo::mutex held, and makes
330 * sure any previous rendering to the buffer is completed. 341 * sure any previous rendering to the buffer is completed.
@@ -334,7 +345,8 @@ ttm_bo_reference(struct ttm_buffer_object *bo)
334 * Returns -ERESTARTSYS if interrupted by a signal. 345 * Returns -ERESTARTSYS if interrupted by a signal.
335 */ 346 */
336extern int ttm_bo_wait(struct ttm_buffer_object *bo, bool lazy, 347extern int ttm_bo_wait(struct ttm_buffer_object *bo, bool lazy,
337 bool interruptible, bool no_wait); 348 bool interruptible, bool no_wait,
349 enum ttm_buffer_usage usage);
338/** 350/**
339 * ttm_bo_validate 351 * ttm_bo_validate
340 * 352 *
diff --git a/include/drm/ttm/ttm_execbuf_util.h b/include/drm/ttm/ttm_execbuf_util.h
index 26cc7f9ffa41..375f29902295 100644
--- a/include/drm/ttm/ttm_execbuf_util.h
+++ b/include/drm/ttm/ttm_execbuf_util.h
@@ -41,20 +41,26 @@
41 * @bo: refcounted buffer object pointer. 41 * @bo: refcounted buffer object pointer.
42 * @new_sync_obj_arg: New sync_obj_arg for @bo, to be used once 42 * @new_sync_obj_arg: New sync_obj_arg for @bo, to be used once
43 * adding a new sync object. 43 * adding a new sync object.
44 * @usage Indicates how @bo is used by the device.
44 * @reserved: Indicates whether @bo has been reserved for validation. 45 * @reserved: Indicates whether @bo has been reserved for validation.
45 * @removed: Indicates whether @bo has been removed from lru lists. 46 * @removed: Indicates whether @bo has been removed from lru lists.
46 * @put_count: Number of outstanding references on bo::list_kref. 47 * @put_count: Number of outstanding references on bo::list_kref.
47 * @old_sync_obj: Pointer to a sync object about to be unreferenced 48 * @old_sync_obj: Pointer to a sync object about to be unreferenced
49 * @old_sync_obj_read: Pointer to a read sync object about to be unreferenced.
50 * @old_sync_obj_write: Pointer to a write sync object about to be unreferenced.
48 */ 51 */
49 52
50struct ttm_validate_buffer { 53struct ttm_validate_buffer {
51 struct list_head head; 54 struct list_head head;
52 struct ttm_buffer_object *bo; 55 struct ttm_buffer_object *bo;
53 void *new_sync_obj_arg; 56 void *new_sync_obj_arg;
57 enum ttm_buffer_usage usage;
54 bool reserved; 58 bool reserved;
55 bool removed; 59 bool removed;
56 int put_count; 60 int put_count;
57 void *old_sync_obj; 61 void *old_sync_obj;
62 void *old_sync_obj_read;
63 void *old_sync_obj_write;
58}; 64};
59 65
60/** 66/**