diff options
author | Michel Dänzer <michel.daenzer@amd.com> | 2015-06-11 05:38:38 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2015-06-11 10:27:54 -0400 |
commit | ee18e599251ed06bf0c8ade7c434a0de311342ca (patch) | |
tree | 568030960f99e0a81a3ebf73b2370fd650097252 /drivers/gpu | |
parent | ebb9bf18636926d5da97136c22e882c5d91fda73 (diff) |
drm/radeon: Make sure radeon_vm_bo_set_addr always unreserves the BO
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
Cc: stable@vger.kernel.org
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>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_vm.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index de42fc4a22b8..9c3377ca17b7 100644 --- 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_device *rdev, | |||
458 | /* make sure object fit at this offset */ | 458 | /* make sure object fit at this offset */ |
459 | eoffset = soffset + size; | 459 | eoffset = soffset + size; |
460 | if (soffset >= eoffset) { | 460 | if (soffset >= eoffset) { |
461 | return -EINVAL; | 461 | r = -EINVAL; |
462 | goto error_unreserve; | ||
462 | } | 463 | } |
463 | 464 | ||
464 | last_pfn = eoffset / RADEON_GPU_PAGE_SIZE; | 465 | last_pfn = eoffset / RADEON_GPU_PAGE_SIZE; |
465 | if (last_pfn > rdev->vm_manager.max_pfn) { | 466 | if (last_pfn > rdev->vm_manager.max_pfn) { |
466 | dev_err(rdev->dev, "va above limit (0x%08X > 0x%08X)\n", | 467 | dev_err(rdev->dev, "va above limit (0x%08X > 0x%08X)\n", |
467 | last_pfn, rdev->vm_manager.max_pfn); | 468 | last_pfn, rdev->vm_manager.max_pfn); |
468 | return -EINVAL; | 469 | r = -EINVAL; |
470 | goto error_unreserve; | ||
469 | } | 471 | } |
470 | 472 | ||
471 | } else { | 473 | } else { |
@@ -486,7 +488,8 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, | |||
486 | "(bo %p 0x%010lx 0x%010lx)\n", bo_va->bo, | 488 | "(bo %p 0x%010lx 0x%010lx)\n", bo_va->bo, |
487 | soffset, tmp->bo, tmp->it.start, tmp->it.last); | 489 | soffset, tmp->bo, tmp->it.start, tmp->it.last); |
488 | mutex_unlock(&vm->mutex); | 490 | mutex_unlock(&vm->mutex); |
489 | return -EINVAL; | 491 | r = -EINVAL; |
492 | goto error_unreserve; | ||
490 | } | 493 | } |
491 | } | 494 | } |
492 | 495 | ||
@@ -497,7 +500,8 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, | |||
497 | tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL); | 500 | tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL); |
498 | if (!tmp) { | 501 | if (!tmp) { |
499 | mutex_unlock(&vm->mutex); | 502 | mutex_unlock(&vm->mutex); |
500 | return -ENOMEM; | 503 | r = -ENOMEM; |
504 | goto error_unreserve; | ||
501 | } | 505 | } |
502 | tmp->it.start = bo_va->it.start; | 506 | tmp->it.start = bo_va->it.start; |
503 | tmp->it.last = bo_va->it.last; | 507 | tmp->it.last = bo_va->it.last; |
@@ -555,7 +559,6 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, | |||
555 | r = radeon_vm_clear_bo(rdev, pt); | 559 | r = radeon_vm_clear_bo(rdev, pt); |
556 | if (r) { | 560 | if (r) { |
557 | radeon_bo_unref(&pt); | 561 | radeon_bo_unref(&pt); |
558 | radeon_bo_reserve(bo_va->bo, false); | ||
559 | return r; | 562 | return r; |
560 | } | 563 | } |
561 | 564 | ||
@@ -575,6 +578,10 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, | |||
575 | 578 | ||
576 | mutex_unlock(&vm->mutex); | 579 | mutex_unlock(&vm->mutex); |
577 | return 0; | 580 | return 0; |
581 | |||
582 | error_unreserve: | ||
583 | radeon_bo_unreserve(bo_va->bo); | ||
584 | return r; | ||
578 | } | 585 | } |
579 | 586 | ||
580 | /** | 587 | /** |