aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/ttm/ttm_bo_vm.c
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2013-11-14 13:49:05 -0500
committerThomas Hellstrom <thellstrom@vmware.com>2013-11-20 06:46:54 -0500
commitc58f009e01c918717379c206a63baa66f56a77f9 (patch)
treeca283d5304390d33e526788141923f8db2008c51 /drivers/gpu/drm/ttm/ttm_bo_vm.c
parent0bc254257bfd9b25f64a68b719ee70a303b6d051 (diff)
drm/ttm: Remove set_need_resched from the ttm fault handler
Addresses "[BUG] completely bonkers use of set_need_resched + VM_FAULT_NOPAGE". In the first occurence it was used to try to be nice while releasing the mmap_sem and retrying the fault to work around a locking inversion. The second occurence was never used. There has been some discussion whether we should change the locking order to mmap_sem -> bo_reserve. This patch doesn't address that issue, and leaves that locking order undefined. The solution that we release the mmap_sem if tryreserve fails and wait for the buffer to become unreserved is something we want in any case, and follows how the core vm system waits for pages to be come unlocked while releasing the mmap_sem. The code also outlines what needs to be changed if we want to establish the locking order as mmap_sem -> bo::reserve. One slight issue that remains with this code is that the fault handler might be prone to starvation if another thread countinously reserves the buffer. IMO that usage pattern is highly unlikely. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Diffstat (limited to 'drivers/gpu/drm/ttm/ttm_bo_vm.c')
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_vm.c26
1 files changed, 20 insertions, 6 deletions
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;