diff options
| author | Christian König <christian.koenig@amd.com> | 2015-04-27 18:04:36 +0300 | 
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2015-04-27 18:29:56 +0300 | 
| commit | c29c0876ec05d51a93508a39b90b92c29ba6423d (patch) | |
| tree | 3223b5c64ff0d798634fd0f4f8a7fb587aa0e551 | |
| parent | 48afbd70ac7b6aa62e8d452091023941d8085f8a (diff) | |
| download | linux-c29c0876ec05d51a93508a39b90b92c29ba6423d.tar.xz | |
drm/radeon: check new address before removing old one
Otherwise the change isn't atomic.
Signed-off-by: Christian König <christian.koenig@amd.com>
CC: stable@vger.kernel.org
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_vm.c | 31 | 
1 files changed, 17 insertions, 14 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index cabcb0aafe03..de42fc4a22b8 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c @@ -473,6 +473,23 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,  	}  	mutex_lock(&vm->mutex); +	soffset /= RADEON_GPU_PAGE_SIZE; +	eoffset /= RADEON_GPU_PAGE_SIZE; +	if (soffset || eoffset) { +		struct interval_tree_node *it; +		it = interval_tree_iter_first(&vm->va, soffset, eoffset - 1); +		if (it && it != &bo_va->it) { +			struct radeon_bo_va *tmp; +			tmp = container_of(it, struct radeon_bo_va, it); +			/* bo and tmp overlap, invalid offset */ +			dev_err(rdev->dev, "bo %p va 0x%010Lx conflict with " +				"(bo %p 0x%010lx 0x%010lx)\n", bo_va->bo, +				soffset, tmp->bo, tmp->it.start, tmp->it.last); +			mutex_unlock(&vm->mutex); +			return -EINVAL; +		} +	} +  	if (bo_va->it.start || bo_va->it.last) {  		if (bo_va->addr) {  			/* add a clone of the bo_va to clear the old address */ @@ -499,21 +516,7 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,  		bo_va->it.last = 0;  	} -	soffset /= RADEON_GPU_PAGE_SIZE; -	eoffset /= RADEON_GPU_PAGE_SIZE;  	if (soffset || eoffset) { -		struct interval_tree_node *it; -		it = interval_tree_iter_first(&vm->va, soffset, eoffset - 1); -		if (it) { -			struct radeon_bo_va *tmp; -			tmp = container_of(it, struct radeon_bo_va, it); -			/* bo and tmp overlap, invalid offset */ -			dev_err(rdev->dev, "bo %p va 0x%010Lx conflict with " -				"(bo %p 0x%010lx 0x%010lx)\n", bo_va->bo, -				soffset, tmp->bo, tmp->it.start, tmp->it.last); -			mutex_unlock(&vm->mutex); -			return -EINVAL; -		}  		bo_va->it.start = soffset;  		bo_va->it.last = eoffset - 1;  		interval_tree_insert(&bo_va->it, &vm->va);  | 
