aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2015-04-27 11:04:36 -0400
committerAlex Deucher <alexander.deucher@amd.com>2015-04-27 11:29:56 -0400
commitc29c0876ec05d51a93508a39b90b92c29ba6423d (patch)
tree3223b5c64ff0d798634fd0f4f8a7fb587aa0e551
parent48afbd70ac7b6aa62e8d452091023941d8085f8a (diff)
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.c31
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,
473 } 473 }
474 474
475 mutex_lock(&vm->mutex); 475 mutex_lock(&vm->mutex);
476 soffset /= RADEON_GPU_PAGE_SIZE;
477 eoffset /= RADEON_GPU_PAGE_SIZE;
478 if (soffset || eoffset) {
479 struct interval_tree_node *it;
480 it = interval_tree_iter_first(&vm->va, soffset, eoffset - 1);
481 if (it && it != &bo_va->it) {
482 struct radeon_bo_va *tmp;
483 tmp = container_of(it, struct radeon_bo_va, it);
484 /* bo and tmp overlap, invalid offset */
485 dev_err(rdev->dev, "bo %p va 0x%010Lx conflict with "
486 "(bo %p 0x%010lx 0x%010lx)\n", bo_va->bo,
487 soffset, tmp->bo, tmp->it.start, tmp->it.last);
488 mutex_unlock(&vm->mutex);
489 return -EINVAL;
490 }
491 }
492
476 if (bo_va->it.start || bo_va->it.last) { 493 if (bo_va->it.start || bo_va->it.last) {
477 if (bo_va->addr) { 494 if (bo_va->addr) {
478 /* add a clone of the bo_va to clear the old address */ 495 /* 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 bo_va->it.last = 0; 516 bo_va->it.last = 0;
500 } 517 }
501 518
502 soffset /= RADEON_GPU_PAGE_SIZE;
503 eoffset /= RADEON_GPU_PAGE_SIZE;
504 if (soffset || eoffset) { 519 if (soffset || eoffset) {
505 struct interval_tree_node *it;
506 it = interval_tree_iter_first(&vm->va, soffset, eoffset - 1);
507 if (it) {
508 struct radeon_bo_va *tmp;
509 tmp = container_of(it, struct radeon_bo_va, it);
510 /* bo and tmp overlap, invalid offset */
511 dev_err(rdev->dev, "bo %p va 0x%010Lx conflict with "
512 "(bo %p 0x%010lx 0x%010lx)\n", bo_va->bo,
513 soffset, tmp->bo, tmp->it.start, tmp->it.last);
514 mutex_unlock(&vm->mutex);
515 return -EINVAL;
516 }
517 bo_va->it.start = soffset; 520 bo_va->it.start = soffset;
518 bo_va->it.last = eoffset - 1; 521 bo_va->it.last = eoffset - 1;
519 interval_tree_insert(&bo_va->it, &vm->va); 522 interval_tree_insert(&bo_va->it, &vm->va);