diff options
| author | Christian König <christian.koenig@amd.com> | 2015-04-27 11:04:36 -0400 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2015-04-27 11:29:56 -0400 |
| commit | c29c0876ec05d51a93508a39b90b92c29ba6423d (patch) | |
| tree | 3223b5c64ff0d798634fd0f4f8a7fb587aa0e551 /drivers | |
| parent | 48afbd70ac7b6aa62e8d452091023941d8085f8a (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>
Diffstat (limited to 'drivers')
| -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, | |||
| 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); |
