Commit c29c0876 authored by Christian König's avatar Christian König Committed by Alex Deucher

drm/radeon: check new address before removing old one

Otherwise the change isn't atomic.
Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
CC: stable@vger.kernel.org
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 48afbd70
...@@ -473,6 +473,23 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, ...@@ -473,6 +473,23 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
} }
mutex_lock(&vm->mutex); 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->it.start || bo_va->it.last) {
if (bo_va->addr) { if (bo_va->addr) {
/* add a clone of the bo_va to clear the old address */ /* 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, ...@@ -499,21 +516,7 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
bo_va->it.last = 0; bo_va->it.last = 0;
} }
soffset /= RADEON_GPU_PAGE_SIZE;
eoffset /= RADEON_GPU_PAGE_SIZE;
if (soffset || eoffset) { 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.start = soffset;
bo_va->it.last = eoffset - 1; bo_va->it.last = eoffset - 1;
interval_tree_insert(&bo_va->it, &vm->va); interval_tree_insert(&bo_va->it, &vm->va);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment