Commit cbe12e74 authored by Thomas Hellstrom's avatar Thomas Hellstrom

drm/ttm: Allow vm fault retries

Make use of the FAULT_FLAG_ALLOW_RETRY flag to allow dropping the
mmap_sem while waiting for bo idle.

FAULT_FLAG_ALLOW_RETRY appears to be primarily designed for disk waits
but should work just as fine for GPU waits..
Signed-off-by: default avatarThomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: default avatarJakob Bornecrantz <jakob@vmware.com>
parent 4695b039
...@@ -41,6 +41,51 @@ ...@@ -41,6 +41,51 @@
#define TTM_BO_VM_NUM_PREFAULT 16 #define TTM_BO_VM_NUM_PREFAULT 16
static int ttm_bo_vm_fault_idle(struct ttm_buffer_object *bo,
struct vm_area_struct *vma,
struct vm_fault *vmf)
{
struct ttm_bo_device *bdev = bo->bdev;
int ret = 0;
spin_lock(&bdev->fence_lock);
if (likely(!test_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags)))
goto out_unlock;
/*
* Quick non-stalling check for idle.
*/
ret = ttm_bo_wait(bo, false, false, true);
if (likely(ret == 0))
goto out_unlock;
/*
* If possible, avoid waiting for GPU with mmap_sem
* held.
*/
if (vmf->flags & FAULT_FLAG_ALLOW_RETRY) {
ret = VM_FAULT_RETRY;
if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT)
goto out_unlock;
up_read(&vma->vm_mm->mmap_sem);
(void) ttm_bo_wait(bo, false, true, false);
goto out_unlock;
}
/*
* Ordinary wait.
*/
ret = ttm_bo_wait(bo, false, true, false);
if (unlikely(ret != 0))
ret = (ret != -ERESTARTSYS) ? VM_FAULT_SIGBUS :
VM_FAULT_NOPAGE;
out_unlock:
spin_unlock(&bdev->fence_lock);
return ret;
}
static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{ {
struct ttm_buffer_object *bo = (struct ttm_buffer_object *) struct ttm_buffer_object *bo = (struct ttm_buffer_object *)
...@@ -91,18 +136,11 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -91,18 +136,11 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
* Wait for buffer data in transit, due to a pipelined * Wait for buffer data in transit, due to a pipelined
* move. * move.
*/ */
ret = ttm_bo_vm_fault_idle(bo, vma, vmf);
spin_lock(&bdev->fence_lock);
if (test_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags)) {
ret = ttm_bo_wait(bo, false, true, false);
spin_unlock(&bdev->fence_lock);
if (unlikely(ret != 0)) { if (unlikely(ret != 0)) {
retval = (ret != -ERESTARTSYS) ? retval = ret;
VM_FAULT_SIGBUS : VM_FAULT_NOPAGE;
goto out_unlock; goto out_unlock;
} }
} else
spin_unlock(&bdev->fence_lock);
ret = ttm_mem_io_lock(man, true); ret = ttm_mem_io_lock(man, true);
if (unlikely(ret != 0)) { if (unlikely(ret != 0)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment