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

Commit 27946e97 authored by Dave Airlie's avatar Dave Airlie
Browse files

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
parents 28adb302 c58f009e
Loading
Loading
Loading
Loading
+34 −1
Original line number Diff line number Diff line
@@ -151,7 +151,7 @@ static void ttm_bo_release_list(struct kref *list_kref)
	atomic_dec(&bo->glob->bo_count);
	if (bo->resv == &bo->ttm_resv)
		reservation_object_fini(&bo->ttm_resv);

	mutex_destroy(&bo->wu_mutex);
	if (bo->destroy)
		bo->destroy(bo);
	else {
@@ -1123,6 +1123,7 @@ int ttm_bo_init(struct ttm_bo_device *bdev,
	INIT_LIST_HEAD(&bo->ddestroy);
	INIT_LIST_HEAD(&bo->swap);
	INIT_LIST_HEAD(&bo->io_reserve_lru);
	mutex_init(&bo->wu_mutex);
	bo->bdev = bdev;
	bo->glob = bdev->glob;
	bo->type = type;
@@ -1704,3 +1705,35 @@ void ttm_bo_swapout_all(struct ttm_bo_device *bdev)
		;
}
EXPORT_SYMBOL(ttm_bo_swapout_all);

/**
 * ttm_bo_wait_unreserved - interruptible wait for a buffer object to become
 * unreserved
 *
 * @bo: Pointer to buffer
 */
int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo)
{
	int ret;

	/*
	 * In the absense of a wait_unlocked API,
	 * Use the bo::wu_mutex to avoid triggering livelocks due to
	 * concurrent use of this function. Note that this use of
	 * bo::wu_mutex can go away if we change locking order to
	 * mmap_sem -> bo::reserve.
	 */
	ret = mutex_lock_interruptible(&bo->wu_mutex);
	if (unlikely(ret != 0))
		return -ERESTARTSYS;
	if (!ww_mutex_is_locked(&bo->resv->lock))
		goto out_unlock;
	ret = ttm_bo_reserve_nolru(bo, true, false, false, NULL);
	if (unlikely(ret != 0))
		goto out_unlock;
	ww_mutex_unlock(&bo->resv->lock);

out_unlock:
	mutex_unlock(&bo->wu_mutex);
	return ret;
}
+5 −2
Original line number Diff line number Diff line
@@ -350,10 +350,13 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
		goto out2;

	/*
	 * Move nonexistent data. NOP.
	 * Don't move nonexistent data. Clear destination instead.
	 */
	if (old_iomap == NULL && ttm == NULL)
	if (old_iomap == NULL &&
	    (ttm == NULL || ttm->state == tt_unpopulated)) {
		memset_io(new_iomap, 0, new_mem->num_pages*PAGE_SIZE);
		goto out2;
	}

	/*
	 * TTM might be null for moves within the same region.
+20 −6
Original line number Diff line number Diff line
@@ -107,13 +107,28 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
	/*
	 * Work around locking order reversal in fault / nopfn
	 * between mmap_sem and bo_reserve: Perform a trylock operation
	 * for reserve, and if it fails, retry the fault after scheduling.
	 * for reserve, and if it fails, retry the fault after waiting
	 * for the buffer to become unreserved.
	 */

	ret = ttm_bo_reserve(bo, true, true, false, 0);
	ret = ttm_bo_reserve(bo, true, true, false, NULL);
	if (unlikely(ret != 0)) {
		if (ret == -EBUSY)
			set_need_resched();
		if (ret != -EBUSY)
			return VM_FAULT_NOPAGE;

		if (vmf->flags & FAULT_FLAG_ALLOW_RETRY) {
			if (!(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) {
				up_read(&vma->vm_mm->mmap_sem);
				(void) ttm_bo_wait_unreserved(bo);
			}

			return VM_FAULT_RETRY;
		}

		/*
		 * If we'd want to change locking order to
		 * mmap_sem -> bo::reserve, we'd use a blocking reserve here
		 * instead of retrying the fault...
		 */
		return VM_FAULT_NOPAGE;
	}

@@ -123,7 +138,6 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
		case 0:
			break;
		case -EBUSY:
			set_need_resched();
		case -ERESTARTSYS:
			retval = VM_FAULT_NOPAGE;
			goto out_unlock;
+3 −1
Original line number Diff line number Diff line
@@ -169,6 +169,7 @@ struct ttm_tt;
 * @offset: The current GPU offset, which can have different meanings
 * depending on the memory type. For SYSTEM type memory, it should be 0.
 * @cur_placement: Hint of current placement.
 * @wu_mutex: Wait unreserved mutex.
 *
 * Base class for TTM buffer object, that deals with data placement and CPU
 * mappings. GPU mappings are really up to the driver, but for simpler GPUs
@@ -250,6 +251,7 @@ struct ttm_buffer_object {

	struct reservation_object *resv;
	struct reservation_object ttm_resv;
	struct mutex wu_mutex;
};

/**
@@ -702,5 +704,5 @@ extern ssize_t ttm_bo_io(struct ttm_bo_device *bdev, struct file *filp,
			 size_t count, loff_t *f_pos, bool write);

extern void ttm_bo_swapout_all(struct ttm_bo_device *bdev);

extern int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo);
#endif