diff options
author | Dave Airlie <airlied@redhat.com> | 2013-11-21 03:46:56 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-11-21 03:46:56 -0500 |
commit | 27946e97108de281e0e9310965ac9a83a4aaa6fe (patch) | |
tree | bc0b2f03c5f25683128a0e2fec3f3a8bced0500e | |
parent | 28adb3026d01da3f6acded3cec817e1a3ba37f44 (diff) | |
parent | c58f009e01c918717379c206a63baa66f56a77f9 (diff) |
Merge branch 'ttm-fixes-3.13' of git://people.freedesktop.org/~thomash/linux into drm-fixes
The set_need_resched() removal fix and yet another fix in
ttm_bo_move_memcpy().
* 'ttm-fixes-3.13' of git://people.freedesktop.org/~thomash/linux:
drm/ttm: Remove set_need_resched from the ttm fault handler
drm/ttm: Don't move non-existing data
-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 |