Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cbe12e74 authored by Thomas Hellstrom's avatar Thomas Hellstrom
Browse files

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
Loading
Loading
Loading
Loading
+50 −12
Original line number Diff line number Diff line
@@ -41,6 +41,51 @@

#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)
{
	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)
	 * Wait for buffer data in transit, due to a pipelined
	 * move.
	 */

	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);
	ret = ttm_bo_vm_fault_idle(bo, vma, vmf);
	if (unlikely(ret != 0)) {
			retval = (ret != -ERESTARTSYS) ?
			    VM_FAULT_SIGBUS : VM_FAULT_NOPAGE;
		retval = ret;
		goto out_unlock;
	}
	} else
		spin_unlock(&bdev->fence_lock);

	ret = ttm_mem_io_lock(man, true);
	if (unlikely(ret != 0)) {