| From ee18e599251ed06bf0c8ade7c434a0de311342ca Mon Sep 17 00:00:00 2001 |
| From: Michel Dänzer <michel.daenzer@amd.com> |
| Date: Thu, 11 Jun 2015 18:38:38 +0900 |
| Subject: drm/radeon: Make sure radeon_vm_bo_set_addr always unreserves the BO |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Michel Dänzer <michel.daenzer@amd.com> |
| |
| commit ee18e599251ed06bf0c8ade7c434a0de311342ca upstream. |
| |
| Some error paths didn't unreserve the BO. This resulted in a deadlock |
| down the road on the next attempt to reserve the (still reserved) BO. |
| |
| Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90873 |
| Reviewed-by: Christian König <christian.koenig@amd.com> |
| Signed-off-by: Michel Dänzer <michel.daenzer@amd.com> |
| Signed-off-by: Alex Deucher <alexander.deucher@amd.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/gpu/drm/radeon/radeon_vm.c | 17 ++++++++++++----- |
| 1 file changed, 12 insertions(+), 5 deletions(-) |
| |
| --- a/drivers/gpu/drm/radeon/radeon_vm.c |
| +++ b/drivers/gpu/drm/radeon/radeon_vm.c |
| @@ -458,14 +458,16 @@ int radeon_vm_bo_set_addr(struct radeon_ |
| /* make sure object fit at this offset */ |
| eoffset = soffset + size; |
| if (soffset >= eoffset) { |
| - return -EINVAL; |
| + r = -EINVAL; |
| + goto error_unreserve; |
| } |
| |
| last_pfn = eoffset / RADEON_GPU_PAGE_SIZE; |
| if (last_pfn > rdev->vm_manager.max_pfn) { |
| dev_err(rdev->dev, "va above limit (0x%08X > 0x%08X)\n", |
| last_pfn, rdev->vm_manager.max_pfn); |
| - return -EINVAL; |
| + r = -EINVAL; |
| + goto error_unreserve; |
| } |
| |
| } else { |
| @@ -486,7 +488,8 @@ int radeon_vm_bo_set_addr(struct radeon_ |
| "(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; |
| + r = -EINVAL; |
| + goto error_unreserve; |
| } |
| } |
| |
| @@ -497,7 +500,8 @@ int radeon_vm_bo_set_addr(struct radeon_ |
| tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL); |
| if (!tmp) { |
| mutex_unlock(&vm->mutex); |
| - return -ENOMEM; |
| + r = -ENOMEM; |
| + goto error_unreserve; |
| } |
| tmp->it.start = bo_va->it.start; |
| tmp->it.last = bo_va->it.last; |
| @@ -555,7 +559,6 @@ int radeon_vm_bo_set_addr(struct radeon_ |
| r = radeon_vm_clear_bo(rdev, pt); |
| if (r) { |
| radeon_bo_unref(&pt); |
| - radeon_bo_reserve(bo_va->bo, false); |
| return r; |
| } |
| |
| @@ -575,6 +578,10 @@ int radeon_vm_bo_set_addr(struct radeon_ |
| |
| mutex_unlock(&vm->mutex); |
| return 0; |
| + |
| +error_unreserve: |
| + radeon_bo_unreserve(bo_va->bo); |
| + return r; |
| } |
| |
| /** |