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

Commit 212c444b authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'ttm-next-3.13' of git://people.freedesktop.org/~thomash/linux into drm-next

- A couple of fixes that never made it into fixes-3.12
- Make NO_EVICT bo's available for shrinkers when on delayed-delete list
- Allow retrying page-faults that need to wait for GPU.

* 'ttm-next-3.13' of git://people.freedesktop.org/~thomash/linux:
  drm/ttm: Fix memory type compatibility check
  drm/ttm: Fix ttm_bo_move_memcpy
  drm/ttm: Handle in-memory region copies
  drm/ttm: Make NO_EVICT bos available to shrinkers pending destruction
  drm/ttm: Allow vm fault retries
parents 1e95ab58 59c8e663
Loading
Loading
Loading
Loading
+33 −13
Original line number Diff line number Diff line
@@ -429,8 +429,20 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)
		sync_obj = driver->sync_obj_ref(bo->sync_obj);
	spin_unlock(&bdev->fence_lock);

	if (!ret)
	if (!ret) {

		/*
		 * Make NO_EVICT bos immediately available to
		 * shrinkers, now that they are queued for
		 * destruction.
		 */
		if (bo->mem.placement & TTM_PL_FLAG_NO_EVICT) {
			bo->mem.placement &= ~TTM_PL_FLAG_NO_EVICT;
			ttm_bo_add_to_lru(bo);
		}

		ww_mutex_unlock(&bo->resv->lock);
	}

	kref_get(&bo->list_kref);
	list_add_tail(&bo->ddestroy, &bdev->ddestroy);
@@ -986,24 +998,32 @@ int ttm_bo_move_buffer(struct ttm_buffer_object *bo,
	return ret;
}

static int ttm_bo_mem_compat(struct ttm_placement *placement,
			     struct ttm_mem_reg *mem)
static bool ttm_bo_mem_compat(struct ttm_placement *placement,
			      struct ttm_mem_reg *mem,
			      uint32_t *new_flags)
{
	int i;

	if (mem->mm_node && placement->lpfn != 0 &&
	    (mem->start < placement->fpfn ||
	     mem->start + mem->num_pages > placement->lpfn))
		return -1;
		return false;

	for (i = 0; i < placement->num_placement; i++) {
		if ((placement->placement[i] & mem->placement &
			TTM_PL_MASK_CACHING) &&
			(placement->placement[i] & mem->placement &
			TTM_PL_MASK_MEM))
			return i;
		*new_flags = placement->placement[i];
		if ((*new_flags & mem->placement & TTM_PL_MASK_CACHING) &&
		    (*new_flags & mem->placement & TTM_PL_MASK_MEM))
			return true;
	}
	return -1;

	for (i = 0; i < placement->num_busy_placement; i++) {
		*new_flags = placement->busy_placement[i];
		if ((*new_flags & mem->placement & TTM_PL_MASK_CACHING) &&
		    (*new_flags & mem->placement & TTM_PL_MASK_MEM))
			return true;
	}

	return false;
}

int ttm_bo_validate(struct ttm_buffer_object *bo,
@@ -1012,6 +1032,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
			bool no_wait_gpu)
{
	int ret;
	uint32_t new_flags;

	lockdep_assert_held(&bo->resv->lock.base);
	/* Check that range is valid */
@@ -1022,8 +1043,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
	/*
	 * Check whether we need to move buffer.
	 */
	ret = ttm_bo_mem_compat(placement, &bo->mem);
	if (ret < 0) {
	if (!ttm_bo_mem_compat(placement, &bo->mem, &new_flags)) {
		ret = ttm_bo_move_buffer(bo, placement, interruptible,
					 no_wait_gpu);
		if (ret)
@@ -1033,7 +1053,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
		 * Use the access and other non-mapping-related flag bits from
		 * the compatible memory placement flags to the active flags
		 */
		ttm_flag_masked(&bo->mem.placement, placement->placement[ret],
		ttm_flag_masked(&bo->mem.placement, new_flags,
				~TTM_PL_MASK_MEMTYPE);
	}
	/*
+19 −11
Original line number Diff line number Diff line
@@ -343,20 +343,26 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
	if (ret)
		goto out;

	/*
	 * Single TTM move. NOP.
	 */
	if (old_iomap == NULL && new_iomap == NULL)
		goto out2;

	/*
	 * Move nonexistent data. NOP.
	 */
	if (old_iomap == NULL && ttm == NULL)
		goto out2;

	if (ttm->state == tt_unpopulated) {
	/*
	 * TTM might be null for moves within the same region.
	 */
	if (ttm && ttm->state == tt_unpopulated) {
		ret = ttm->bdev->driver->ttm_tt_populate(ttm);
		if (ret) {
			/* if we fail here don't nuke the mm node
			 * as the bo still owns it */
			old_copy.mm_node = NULL;
		if (ret)
			goto out1;
	}
	}

	add = 0;
	dir = 1;
@@ -381,12 +387,9 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
						   prot);
		} else
			ret = ttm_copy_io_page(new_iomap, old_iomap, page);
		if (ret) {
			/* failing here, means keep old copy as-is */
			old_copy.mm_node = NULL;
		if (ret)
			goto out1;
	}
	}
	mb();
out2:
	old_copy = *old_mem;
@@ -403,6 +406,11 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
	ttm_mem_reg_iounmap(bdev, old_mem, new_iomap);
out:
	ttm_mem_reg_iounmap(bdev, &old_copy, old_iomap);

	/*
	 * On error, keep the mm node!
	 */
	if (!ret)
		ttm_bo_mem_put(bo, &old_copy);
	return ret;
}
+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)) {