diff options
| -rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo.c | 35 | ||||
| -rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo_util.c | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo_vm.c | 26 | ||||
| -rw-r--r-- | include/drm/ttm/ttm_bo_api.h | 4 |
4 files changed, 62 insertions, 10 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 8d5a646ebe6a..07e02c4bf5a8 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c | |||
| @@ -151,7 +151,7 @@ static void ttm_bo_release_list(struct kref *list_kref) | |||
| 151 | atomic_dec(&bo->glob->bo_count); | 151 | atomic_dec(&bo->glob->bo_count); |
| 152 | if (bo->resv == &bo->ttm_resv) | 152 | if (bo->resv == &bo->ttm_resv) |
| 153 | reservation_object_fini(&bo->ttm_resv); | 153 | reservation_object_fini(&bo->ttm_resv); |
| 154 | 154 | mutex_destroy(&bo->wu_mutex); | |
| 155 | if (bo->destroy) | 155 | if (bo->destroy) |
| 156 | bo->destroy(bo); | 156 | bo->destroy(bo); |
| 157 | else { | 157 | else { |
| @@ -1123,6 +1123,7 @@ int ttm_bo_init(struct ttm_bo_device *bdev, | |||
| 1123 | INIT_LIST_HEAD(&bo->ddestroy); | 1123 | INIT_LIST_HEAD(&bo->ddestroy); |
| 1124 | INIT_LIST_HEAD(&bo->swap); | 1124 | INIT_LIST_HEAD(&bo->swap); |
| 1125 | INIT_LIST_HEAD(&bo->io_reserve_lru); | 1125 | INIT_LIST_HEAD(&bo->io_reserve_lru); |
| 1126 | mutex_init(&bo->wu_mutex); | ||
| 1126 | bo->bdev = bdev; | 1127 | bo->bdev = bdev; |
| 1127 | bo->glob = bdev->glob; | 1128 | bo->glob = bdev->glob; |
| 1128 | bo->type = type; | 1129 | bo->type = type; |
| @@ -1704,3 +1705,35 @@ void ttm_bo_swapout_all(struct ttm_bo_device *bdev) | |||
| 1704 | ; | 1705 | ; |
| 1705 | } | 1706 | } |
| 1706 | EXPORT_SYMBOL(ttm_bo_swapout_all); | 1707 | EXPORT_SYMBOL(ttm_bo_swapout_all); |
| 1708 | |||
| 1709 | /** | ||
| 1710 | * ttm_bo_wait_unreserved - interruptible wait for a buffer object to become | ||
| 1711 | * unreserved | ||
| 1712 | * | ||
| 1713 | * @bo: Pointer to buffer | ||
| 1714 | */ | ||
| 1715 | int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo) | ||
| 1716 | { | ||
| 1717 | int ret; | ||
| 1718 | |||
| 1719 | /* | ||
| 1720 | * In the absense of a wait_unlocked API, | ||
| 1721 | * Use the bo::wu_mutex to avoid triggering livelocks due to | ||
| 1722 | * concurrent use of this function. Note that this use of | ||
| 1723 | * bo::wu_mutex can go away if we change locking order to | ||
| 1724 | * mmap_sem -> bo::reserve. | ||
| 1725 | */ | ||
| 1726 | ret = mutex_lock_interruptible(&bo->wu_mutex); | ||
| 1727 | if (unlikely(ret != 0)) | ||
| 1728 | return -ERESTARTSYS; | ||
| 1729 | if (!ww_mutex_is_locked(&bo->resv->lock)) | ||
| 1730 | goto out_unlock; | ||
| 1731 | ret = ttm_bo_reserve_nolru(bo, true, false, false, NULL); | ||
| 1732 | if (unlikely(ret != 0)) | ||
| 1733 | goto out_unlock; | ||
| 1734 | ww_mutex_unlock(&bo->resv->lock); | ||
| 1735 | |||
| 1736 | out_unlock: | ||
| 1737 | mutex_unlock(&bo->wu_mutex); | ||
| 1738 | return ret; | ||
| 1739 | } | ||
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 4834c463c38b..15b86a94949d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c | |||
| @@ -350,10 +350,13 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, | |||
| 350 | goto out2; | 350 | goto out2; |
| 351 | 351 | ||
| 352 | /* | 352 | /* |
| 353 | * Move nonexistent data. NOP. | 353 | * Don't move nonexistent data. Clear destination instead. |
| 354 | */ | 354 | */ |
| 355 | if (old_iomap == NULL && ttm == NULL) | 355 | if (old_iomap == NULL && |
| 356 | (ttm == NULL || ttm->state == tt_unpopulated)) { | ||
| 357 | memset_io(new_iomap, 0, new_mem->num_pages*PAGE_SIZE); | ||
| 356 | goto out2; | 358 | goto out2; |
| 359 | } | ||
| 357 | 360 | ||
| 358 | /* | 361 | /* |
| 359 | * TTM might be null for moves within the same region. | 362 | * TTM might be null for moves within the same region. |
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index ac617f3ecd0c..b249ab9b1eb2 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c | |||
| @@ -107,13 +107,28 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 107 | /* | 107 | /* |
| 108 | * Work around locking order reversal in fault / nopfn | 108 | * Work around locking order reversal in fault / nopfn |
| 109 | * between mmap_sem and bo_reserve: Perform a trylock operation | 109 | * between mmap_sem and bo_reserve: Perform a trylock operation |
| 110 | * for reserve, and if it fails, retry the fault after scheduling. | 110 | * for reserve, and if it fails, retry the fault after waiting |
| 111 | * for the buffer to become unreserved. | ||
| 111 | */ | 112 | */ |
| 112 | 113 | ret = ttm_bo_reserve(bo, true, true, false, NULL); | |
| 113 | ret = ttm_bo_reserve(bo, true, true, false, 0); | ||
| 114 | if (unlikely(ret != 0)) { | 114 | if (unlikely(ret != 0)) { |
| 115 | if (ret == -EBUSY) | 115 | if (ret != -EBUSY) |
| 116 | set_need_resched(); | 116 | return VM_FAULT_NOPAGE; |
| 117 | |||
| 118 | if (vmf->flags & FAULT_FLAG_ALLOW_RETRY) { | ||
| 119 | if (!(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) { | ||
| 120 | up_read(&vma->vm_mm->mmap_sem); | ||
| 121 | (void) ttm_bo_wait_unreserved(bo); | ||
| 122 | } | ||
| 123 | |||
| 124 | return VM_FAULT_RETRY; | ||
| 125 | } | ||
| 126 | |||
| 127 | /* | ||
| 128 | * If we'd want to change locking order to | ||
| 129 | * mmap_sem -> bo::reserve, we'd use a blocking reserve here | ||
| 130 | * instead of retrying the fault... | ||
| 131 | */ | ||
| 117 | return VM_FAULT_NOPAGE; | 132 | return VM_FAULT_NOPAGE; |
| 118 | } | 133 | } |
| 119 | 134 | ||
| @@ -123,7 +138,6 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 123 | case 0: | 138 | case 0: |
| 124 | break; | 139 | break; |
| 125 | case -EBUSY: | 140 | case -EBUSY: |
| 126 | set_need_resched(); | ||
| 127 | case -ERESTARTSYS: | 141 | case -ERESTARTSYS: |
| 128 | retval = VM_FAULT_NOPAGE; | 142 | retval = VM_FAULT_NOPAGE; |
| 129 | goto out_unlock; | 143 | goto out_unlock; |
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 751eaffbf0d5..ee127ec33c60 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h | |||
| @@ -169,6 +169,7 @@ struct ttm_tt; | |||
| 169 | * @offset: The current GPU offset, which can have different meanings | 169 | * @offset: The current GPU offset, which can have different meanings |
| 170 | * depending on the memory type. For SYSTEM type memory, it should be 0. | 170 | * depending on the memory type. For SYSTEM type memory, it should be 0. |
| 171 | * @cur_placement: Hint of current placement. | 171 | * @cur_placement: Hint of current placement. |
| 172 | * @wu_mutex: Wait unreserved mutex. | ||
| 172 | * | 173 | * |
| 173 | * Base class for TTM buffer object, that deals with data placement and CPU | 174 | * Base class for TTM buffer object, that deals with data placement and CPU |
| 174 | * mappings. GPU mappings are really up to the driver, but for simpler GPUs | 175 | * mappings. GPU mappings are really up to the driver, but for simpler GPUs |
| @@ -250,6 +251,7 @@ struct ttm_buffer_object { | |||
| 250 | 251 | ||
| 251 | struct reservation_object *resv; | 252 | struct reservation_object *resv; |
| 252 | struct reservation_object ttm_resv; | 253 | struct reservation_object ttm_resv; |
| 254 | struct mutex wu_mutex; | ||
| 253 | }; | 255 | }; |
| 254 | 256 | ||
| 255 | /** | 257 | /** |
| @@ -702,5 +704,5 @@ extern ssize_t ttm_bo_io(struct ttm_bo_device *bdev, struct file *filp, | |||
| 702 | size_t count, loff_t *f_pos, bool write); | 704 | size_t count, loff_t *f_pos, bool write); |
| 703 | 705 | ||
| 704 | extern void ttm_bo_swapout_all(struct ttm_bo_device *bdev); | 706 | extern void ttm_bo_swapout_all(struct ttm_bo_device *bdev); |
| 705 | 707 | extern int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo); | |
| 706 | #endif | 708 | #endif |
