diff options
| author | Dave Airlie <airlied@redhat.com> | 2013-11-21 18:46:56 +1000 | 
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2013-11-21 18:46:56 +1000 | 
| commit | 27946e97108de281e0e9310965ac9a83a4aaa6fe (patch) | |
| tree | bc0b2f03c5f25683128a0e2fec3f3a8bced0500e /drivers/gpu | |
| parent | 28adb3026d01da3f6acded3cec817e1a3ba37f44 (diff) | |
| parent | c58f009e01c918717379c206a63baa66f56a77f9 (diff) | |
| download | linux-27946e97108de281e0e9310965ac9a83a4aaa6fe.tar.bz2 | |
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
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo.c | 35 | ||||
| -rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo_util.c | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo_vm.c | 26 | 
3 files changed, 59 insertions, 9 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 8d5a646ebe6a..07e02c4bf5a8 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -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; +} diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 4834c463c38b..15b86a94949d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -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. 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)  	/*  	 * 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;  |