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
This commit is contained in:
commit
27946e9710
4 changed files with 62 additions and 10 deletions
|
@ -151,7 +151,7 @@ static void ttm_bo_release_list(struct kref *list_kref)
|
||||||
atomic_dec(&bo->glob->bo_count);
|
atomic_dec(&bo->glob->bo_count);
|
||||||
if (bo->resv == &bo->ttm_resv)
|
if (bo->resv == &bo->ttm_resv)
|
||||||
reservation_object_fini(&bo->ttm_resv);
|
reservation_object_fini(&bo->ttm_resv);
|
||||||
|
mutex_destroy(&bo->wu_mutex);
|
||||||
if (bo->destroy)
|
if (bo->destroy)
|
||||||
bo->destroy(bo);
|
bo->destroy(bo);
|
||||||
else {
|
else {
|
||||||
|
@ -1123,6 +1123,7 @@ int ttm_bo_init(struct ttm_bo_device *bdev,
|
||||||
INIT_LIST_HEAD(&bo->ddestroy);
|
INIT_LIST_HEAD(&bo->ddestroy);
|
||||||
INIT_LIST_HEAD(&bo->swap);
|
INIT_LIST_HEAD(&bo->swap);
|
||||||
INIT_LIST_HEAD(&bo->io_reserve_lru);
|
INIT_LIST_HEAD(&bo->io_reserve_lru);
|
||||||
|
mutex_init(&bo->wu_mutex);
|
||||||
bo->bdev = bdev;
|
bo->bdev = bdev;
|
||||||
bo->glob = bdev->glob;
|
bo->glob = bdev->glob;
|
||||||
bo->type = type;
|
bo->type = type;
|
||||||
|
@ -1704,3 +1705,35 @@ void ttm_bo_swapout_all(struct ttm_bo_device *bdev)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ttm_bo_swapout_all);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -350,10 +350,13 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
|
||||||
goto out2;
|
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;
|
goto out2;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TTM might be null for moves within the same region.
|
* TTM might be null for moves within the same region.
|
||||||
|
|
|
@ -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
|
* Work around locking order reversal in fault / nopfn
|
||||||
* between mmap_sem and bo_reserve: Perform a trylock operation
|
* 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, NULL);
|
||||||
ret = ttm_bo_reserve(bo, true, true, false, 0);
|
|
||||||
if (unlikely(ret != 0)) {
|
if (unlikely(ret != 0)) {
|
||||||
if (ret == -EBUSY)
|
if (ret != -EBUSY)
|
||||||
set_need_resched();
|
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;
|
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:
|
case 0:
|
||||||
break;
|
break;
|
||||||
case -EBUSY:
|
case -EBUSY:
|
||||||
set_need_resched();
|
|
||||||
case -ERESTARTSYS:
|
case -ERESTARTSYS:
|
||||||
retval = VM_FAULT_NOPAGE;
|
retval = VM_FAULT_NOPAGE;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
|
@ -169,6 +169,7 @@ struct ttm_tt;
|
||||||
* @offset: The current GPU offset, which can have different meanings
|
* @offset: The current GPU offset, which can have different meanings
|
||||||
* depending on the memory type. For SYSTEM type memory, it should be 0.
|
* depending on the memory type. For SYSTEM type memory, it should be 0.
|
||||||
* @cur_placement: Hint of current placement.
|
* @cur_placement: Hint of current placement.
|
||||||
|
* @wu_mutex: Wait unreserved mutex.
|
||||||
*
|
*
|
||||||
* Base class for TTM buffer object, that deals with data placement and CPU
|
* 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
|
* 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 *resv;
|
||||||
struct reservation_object ttm_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);
|
size_t count, loff_t *f_pos, bool write);
|
||||||
|
|
||||||
extern void ttm_bo_swapout_all(struct ttm_bo_device *bdev);
|
extern void ttm_bo_swapout_all(struct ttm_bo_device *bdev);
|
||||||
|
extern int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue