diff options
author | Christian König <christian.koenig@amd.com> | 2017-11-08 09:55:44 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2017-12-06 12:47:48 -0500 |
commit | 6ba435812e0d85b016670ba7324d1bb1369d8428 (patch) | |
tree | 651813f7084a06df446bb5a8c3f410b976101594 /drivers/gpu/drm | |
parent | 56f3df448c9458ffd4c2ae62c09afc99f7ab277d (diff) |
drm/ttm: optimize ttm_mem_evict_first v5
Deleted BOs with the same reservation object can be reaped even if they
can't be reserved.
v2: rebase and we still need to remove/add the BO from/to the LRU.
v3: fix remove/add one more time, cleanup the logic a bit
v4: we should still check if the eviction is valuable
v5: add comment suggested by Michel
Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-and-Tested-by: Michel Dänzer <michel.daenzer@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo.c | 54 |
1 files changed, 33 insertions, 21 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 3aa63c4679f0..07d9c6e5b6ca 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c | |||
@@ -734,47 +734,57 @@ bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, | |||
734 | EXPORT_SYMBOL(ttm_bo_eviction_valuable); | 734 | EXPORT_SYMBOL(ttm_bo_eviction_valuable); |
735 | 735 | ||
736 | static int ttm_mem_evict_first(struct ttm_bo_device *bdev, | 736 | static int ttm_mem_evict_first(struct ttm_bo_device *bdev, |
737 | uint32_t mem_type, | 737 | struct reservation_object *resv, |
738 | const struct ttm_place *place, | 738 | uint32_t mem_type, |
739 | bool interruptible, | 739 | const struct ttm_place *place, |
740 | bool no_wait_gpu) | 740 | bool interruptible, |
741 | bool no_wait_gpu) | ||
741 | { | 742 | { |
742 | struct ttm_bo_global *glob = bdev->glob; | 743 | struct ttm_bo_global *glob = bdev->glob; |
743 | struct ttm_mem_type_manager *man = &bdev->man[mem_type]; | 744 | struct ttm_mem_type_manager *man = &bdev->man[mem_type]; |
744 | struct ttm_buffer_object *bo; | 745 | struct ttm_buffer_object *bo = NULL; |
745 | int ret = -EBUSY; | 746 | bool locked = false; |
746 | unsigned i; | 747 | unsigned i; |
748 | int ret; | ||
747 | 749 | ||
748 | spin_lock(&glob->lru_lock); | 750 | spin_lock(&glob->lru_lock); |
749 | for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { | 751 | for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { |
750 | list_for_each_entry(bo, &man->lru[i], lru) { | 752 | list_for_each_entry(bo, &man->lru[i], lru) { |
751 | ret = reservation_object_trylock(bo->resv) ? 0 : -EBUSY; | 753 | if (bo->resv == resv) { |
752 | if (ret) | 754 | if (list_empty(&bo->ddestroy)) |
753 | continue; | 755 | continue; |
756 | } else { | ||
757 | locked = reservation_object_trylock(bo->resv); | ||
758 | if (!locked) | ||
759 | continue; | ||
760 | } | ||
754 | 761 | ||
755 | if (place && !bdev->driver->eviction_valuable(bo, | 762 | if (place && !bdev->driver->eviction_valuable(bo, |
756 | place)) { | 763 | place)) { |
757 | reservation_object_unlock(bo->resv); | 764 | if (locked) |
758 | ret = -EBUSY; | 765 | reservation_object_unlock(bo->resv); |
759 | continue; | 766 | continue; |
760 | } | 767 | } |
761 | |||
762 | break; | 768 | break; |
763 | } | 769 | } |
764 | 770 | ||
765 | if (!ret) | 771 | /* If the inner loop terminated early, we have our candidate */ |
772 | if (&bo->lru != &man->lru[i]) | ||
766 | break; | 773 | break; |
774 | |||
775 | bo = NULL; | ||
767 | } | 776 | } |
768 | 777 | ||
769 | if (ret) { | 778 | if (!bo) { |
770 | spin_unlock(&glob->lru_lock); | 779 | spin_unlock(&glob->lru_lock); |
771 | return ret; | 780 | return -EBUSY; |
772 | } | 781 | } |
773 | 782 | ||
774 | kref_get(&bo->list_kref); | 783 | kref_get(&bo->list_kref); |
775 | 784 | ||
776 | if (!list_empty(&bo->ddestroy)) { | 785 | if (!list_empty(&bo->ddestroy)) { |
777 | ret = ttm_bo_cleanup_refs(bo, interruptible, no_wait_gpu, true); | 786 | ret = ttm_bo_cleanup_refs(bo, interruptible, no_wait_gpu, |
787 | locked); | ||
778 | kref_put(&bo->list_kref, ttm_bo_release_list); | 788 | kref_put(&bo->list_kref, ttm_bo_release_list); |
779 | return ret; | 789 | return ret; |
780 | } | 790 | } |
@@ -782,10 +792,11 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev, | |||
782 | ttm_bo_del_from_lru(bo); | 792 | ttm_bo_del_from_lru(bo); |
783 | spin_unlock(&glob->lru_lock); | 793 | spin_unlock(&glob->lru_lock); |
784 | 794 | ||
785 | BUG_ON(ret != 0); | ||
786 | |||
787 | ret = ttm_bo_evict(bo, interruptible, no_wait_gpu); | 795 | ret = ttm_bo_evict(bo, interruptible, no_wait_gpu); |
788 | ttm_bo_unreserve(bo); | 796 | if (locked) |
797 | ttm_bo_unreserve(bo); | ||
798 | else | ||
799 | ttm_bo_add_to_lru(bo); | ||
789 | 800 | ||
790 | kref_put(&bo->list_kref, ttm_bo_release_list); | 801 | kref_put(&bo->list_kref, ttm_bo_release_list); |
791 | return ret; | 802 | return ret; |
@@ -849,7 +860,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, | |||
849 | return ret; | 860 | return ret; |
850 | if (mem->mm_node) | 861 | if (mem->mm_node) |
851 | break; | 862 | break; |
852 | ret = ttm_mem_evict_first(bdev, mem_type, place, | 863 | ret = ttm_mem_evict_first(bdev, bo->resv, mem_type, place, |
853 | interruptible, no_wait_gpu); | 864 | interruptible, no_wait_gpu); |
854 | if (unlikely(ret != 0)) | 865 | if (unlikely(ret != 0)) |
855 | return ret; | 866 | return ret; |
@@ -1352,7 +1363,8 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev, | |||
1352 | for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { | 1363 | for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { |
1353 | while (!list_empty(&man->lru[i])) { | 1364 | while (!list_empty(&man->lru[i])) { |
1354 | spin_unlock(&glob->lru_lock); | 1365 | spin_unlock(&glob->lru_lock); |
1355 | ret = ttm_mem_evict_first(bdev, mem_type, NULL, false, false); | 1366 | ret = ttm_mem_evict_first(bdev, NULL, mem_type, NULL, |
1367 | false, false); | ||
1356 | if (ret) | 1368 | if (ret) |
1357 | return ret; | 1369 | return ret; |
1358 | spin_lock(&glob->lru_lock); | 1370 | spin_lock(&glob->lru_lock); |