diff options
author | Christian König <christian.koenig@amd.com> | 2018-09-11 05:50:57 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-09-19 13:38:41 -0400 |
commit | 403009bfba45163887398652762ed1fc6645181c (patch) | |
tree | 55d50f036ed77a19acffb3f736190878c6130280 /drivers/gpu/drm/amd/amdgpu | |
parent | c33adbc7285f72dbd86aedba858e9570cd9f9c99 (diff) |
drm/amdgpu: fix shadow BO restoring
Don't grab the reservation lock any more and simplify the handling quite
a bit.
Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Huang Rui <ray.huang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 109 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 46 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 8 |
3 files changed, 43 insertions, 120 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 0267fae316d7..bd79d0a31942 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | |||
@@ -2951,54 +2951,6 @@ static int amdgpu_device_ip_post_soft_reset(struct amdgpu_device *adev) | |||
2951 | } | 2951 | } |
2952 | 2952 | ||
2953 | /** | 2953 | /** |
2954 | * amdgpu_device_recover_vram_from_shadow - restore shadowed VRAM buffers | ||
2955 | * | ||
2956 | * @adev: amdgpu_device pointer | ||
2957 | * @ring: amdgpu_ring for the engine handling the buffer operations | ||
2958 | * @bo: amdgpu_bo buffer whose shadow is being restored | ||
2959 | * @fence: dma_fence associated with the operation | ||
2960 | * | ||
2961 | * Restores the VRAM buffer contents from the shadow in GTT. Used to | ||
2962 | * restore things like GPUVM page tables after a GPU reset where | ||
2963 | * the contents of VRAM might be lost. | ||
2964 | * Returns 0 on success, negative error code on failure. | ||
2965 | */ | ||
2966 | static int amdgpu_device_recover_vram_from_shadow(struct amdgpu_device *adev, | ||
2967 | struct amdgpu_ring *ring, | ||
2968 | struct amdgpu_bo *bo, | ||
2969 | struct dma_fence **fence) | ||
2970 | { | ||
2971 | uint32_t domain; | ||
2972 | int r; | ||
2973 | |||
2974 | if (!bo->shadow) | ||
2975 | return 0; | ||
2976 | |||
2977 | r = amdgpu_bo_reserve(bo, true); | ||
2978 | if (r) | ||
2979 | return r; | ||
2980 | domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type); | ||
2981 | /* if bo has been evicted, then no need to recover */ | ||
2982 | if (domain == AMDGPU_GEM_DOMAIN_VRAM) { | ||
2983 | r = amdgpu_bo_validate(bo->shadow); | ||
2984 | if (r) { | ||
2985 | DRM_ERROR("bo validate failed!\n"); | ||
2986 | goto err; | ||
2987 | } | ||
2988 | |||
2989 | r = amdgpu_bo_restore_from_shadow(adev, ring, bo, | ||
2990 | NULL, fence, true); | ||
2991 | if (r) { | ||
2992 | DRM_ERROR("recover page table failed!\n"); | ||
2993 | goto err; | ||
2994 | } | ||
2995 | } | ||
2996 | err: | ||
2997 | amdgpu_bo_unreserve(bo); | ||
2998 | return r; | ||
2999 | } | ||
3000 | |||
3001 | /** | ||
3002 | * amdgpu_device_recover_vram - Recover some VRAM contents | 2954 | * amdgpu_device_recover_vram - Recover some VRAM contents |
3003 | * | 2955 | * |
3004 | * @adev: amdgpu_device pointer | 2956 | * @adev: amdgpu_device pointer |
@@ -3006,16 +2958,15 @@ err: | |||
3006 | * Restores the contents of VRAM buffers from the shadows in GTT. Used to | 2958 | * Restores the contents of VRAM buffers from the shadows in GTT. Used to |
3007 | * restore things like GPUVM page tables after a GPU reset where | 2959 | * restore things like GPUVM page tables after a GPU reset where |
3008 | * the contents of VRAM might be lost. | 2960 | * the contents of VRAM might be lost. |
3009 | * Returns 0 on success, 1 on failure. | 2961 | * |
2962 | * Returns: | ||
2963 | * 0 on success, negative error code on failure. | ||
3010 | */ | 2964 | */ |
3011 | static int amdgpu_device_recover_vram(struct amdgpu_device *adev) | 2965 | static int amdgpu_device_recover_vram(struct amdgpu_device *adev) |
3012 | { | 2966 | { |
3013 | struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; | ||
3014 | struct amdgpu_bo *bo, *tmp; | ||
3015 | struct dma_fence *fence = NULL, *next = NULL; | 2967 | struct dma_fence *fence = NULL, *next = NULL; |
3016 | long r = 1; | 2968 | struct amdgpu_bo *shadow; |
3017 | int i = 0; | 2969 | long r = 1, tmo; |
3018 | long tmo; | ||
3019 | 2970 | ||
3020 | if (amdgpu_sriov_runtime(adev)) | 2971 | if (amdgpu_sriov_runtime(adev)) |
3021 | tmo = msecs_to_jiffies(8000); | 2972 | tmo = msecs_to_jiffies(8000); |
@@ -3024,44 +2975,40 @@ static int amdgpu_device_recover_vram(struct amdgpu_device *adev) | |||
3024 | 2975 | ||
3025 | DRM_INFO("recover vram bo from shadow start\n"); | 2976 | DRM_INFO("recover vram bo from shadow start\n"); |
3026 | mutex_lock(&adev->shadow_list_lock); | 2977 | mutex_lock(&adev->shadow_list_lock); |
3027 | list_for_each_entry_safe(bo, tmp, &adev->shadow_list, shadow_list) { | 2978 | list_for_each_entry(shadow, &adev->shadow_list, shadow_list) { |
3028 | next = NULL; | 2979 | |
3029 | amdgpu_device_recover_vram_from_shadow(adev, ring, bo, &next); | 2980 | /* No need to recover an evicted BO */ |
2981 | if (shadow->tbo.mem.mem_type != TTM_PL_TT || | ||
2982 | shadow->parent->tbo.mem.mem_type != TTM_PL_VRAM) | ||
2983 | continue; | ||
2984 | |||
2985 | r = amdgpu_bo_restore_shadow(shadow, &next); | ||
2986 | if (r) | ||
2987 | break; | ||
2988 | |||
3030 | if (fence) { | 2989 | if (fence) { |
3031 | r = dma_fence_wait_timeout(fence, false, tmo); | 2990 | r = dma_fence_wait_timeout(fence, false, tmo); |
3032 | if (r == 0) | 2991 | dma_fence_put(fence); |
3033 | pr_err("wait fence %p[%d] timeout\n", fence, i); | 2992 | fence = next; |
3034 | else if (r < 0) | 2993 | if (r <= 0) |
3035 | pr_err("wait fence %p[%d] interrupted\n", fence, i); | ||
3036 | if (r < 1) { | ||
3037 | dma_fence_put(fence); | ||
3038 | fence = next; | ||
3039 | break; | 2994 | break; |
3040 | } | 2995 | } else { |
3041 | i++; | 2996 | fence = next; |
3042 | } | 2997 | } |
3043 | |||
3044 | dma_fence_put(fence); | ||
3045 | fence = next; | ||
3046 | } | 2998 | } |
3047 | mutex_unlock(&adev->shadow_list_lock); | 2999 | mutex_unlock(&adev->shadow_list_lock); |
3048 | 3000 | ||
3049 | if (fence) { | 3001 | if (fence) |
3050 | r = dma_fence_wait_timeout(fence, false, tmo); | 3002 | tmo = dma_fence_wait_timeout(fence, false, tmo); |
3051 | if (r == 0) | ||
3052 | pr_err("wait fence %p[%d] timeout\n", fence, i); | ||
3053 | else if (r < 0) | ||
3054 | pr_err("wait fence %p[%d] interrupted\n", fence, i); | ||
3055 | |||
3056 | } | ||
3057 | dma_fence_put(fence); | 3003 | dma_fence_put(fence); |
3058 | 3004 | ||
3059 | if (r > 0) | 3005 | if (r <= 0 || tmo <= 0) { |
3060 | DRM_INFO("recover vram bo from shadow done\n"); | ||
3061 | else | ||
3062 | DRM_ERROR("recover vram bo from shadow failed\n"); | 3006 | DRM_ERROR("recover vram bo from shadow failed\n"); |
3007 | return -EIO; | ||
3008 | } | ||
3063 | 3009 | ||
3064 | return (r > 0) ? 0 : 1; | 3010 | DRM_INFO("recover vram bo from shadow done\n"); |
3011 | return 0; | ||
3065 | } | 3012 | } |
3066 | 3013 | ||
3067 | /** | 3014 | /** |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 524c21d56f75..113738cbb32c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | |||
@@ -553,7 +553,7 @@ static int amdgpu_bo_create_shadow(struct amdgpu_device *adev, | |||
553 | if (!r) { | 553 | if (!r) { |
554 | bo->shadow->parent = amdgpu_bo_ref(bo); | 554 | bo->shadow->parent = amdgpu_bo_ref(bo); |
555 | mutex_lock(&adev->shadow_list_lock); | 555 | mutex_lock(&adev->shadow_list_lock); |
556 | list_add_tail(&bo->shadow_list, &adev->shadow_list); | 556 | list_add_tail(&bo->shadow->shadow_list, &adev->shadow_list); |
557 | mutex_unlock(&adev->shadow_list_lock); | 557 | mutex_unlock(&adev->shadow_list_lock); |
558 | } | 558 | } |
559 | 559 | ||
@@ -685,13 +685,10 @@ retry: | |||
685 | } | 685 | } |
686 | 686 | ||
687 | /** | 687 | /** |
688 | * amdgpu_bo_restore_from_shadow - restore an &amdgpu_bo buffer object | 688 | * amdgpu_bo_restore_shadow - restore an &amdgpu_bo shadow |
689 | * @adev: amdgpu device object | 689 | * |
690 | * @ring: amdgpu_ring for the engine handling the buffer operations | 690 | * @shadow: &amdgpu_bo shadow to be restored |
691 | * @bo: &amdgpu_bo buffer to be restored | ||
692 | * @resv: reservation object with embedded fence | ||
693 | * @fence: dma_fence associated with the operation | 691 | * @fence: dma_fence associated with the operation |
694 | * @direct: whether to submit the job directly | ||
695 | * | 692 | * |
696 | * Copies a buffer object's shadow content back to the object. | 693 | * Copies a buffer object's shadow content back to the object. |
697 | * This is used for recovering a buffer from its shadow in case of a gpu | 694 | * This is used for recovering a buffer from its shadow in case of a gpu |
@@ -700,36 +697,19 @@ retry: | |||
700 | * Returns: | 697 | * Returns: |
701 | * 0 for success or a negative error code on failure. | 698 | * 0 for success or a negative error code on failure. |
702 | */ | 699 | */ |
703 | int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev, | 700 | int amdgpu_bo_restore_shadow(struct amdgpu_bo *shadow, struct dma_fence **fence) |
704 | struct amdgpu_ring *ring, | ||
705 | struct amdgpu_bo *bo, | ||
706 | struct reservation_object *resv, | ||
707 | struct dma_fence **fence, | ||
708 | bool direct) | ||
709 | 701 | ||
710 | { | 702 | { |
711 | struct amdgpu_bo *shadow = bo->shadow; | 703 | struct amdgpu_device *adev = amdgpu_ttm_adev(shadow->tbo.bdev); |
712 | uint64_t bo_addr, shadow_addr; | 704 | struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; |
713 | int r; | 705 | uint64_t shadow_addr, parent_addr; |
714 | |||
715 | if (!shadow) | ||
716 | return -EINVAL; | ||
717 | |||
718 | bo_addr = amdgpu_bo_gpu_offset(bo); | ||
719 | shadow_addr = amdgpu_bo_gpu_offset(bo->shadow); | ||
720 | |||
721 | r = reservation_object_reserve_shared(bo->tbo.resv); | ||
722 | if (r) | ||
723 | goto err; | ||
724 | 706 | ||
725 | r = amdgpu_copy_buffer(ring, shadow_addr, bo_addr, | 707 | shadow_addr = amdgpu_bo_gpu_offset(shadow); |
726 | amdgpu_bo_size(bo), resv, fence, | 708 | parent_addr = amdgpu_bo_gpu_offset(shadow->parent); |
727 | direct, false); | ||
728 | if (!r) | ||
729 | amdgpu_bo_fence(bo, *fence, true); | ||
730 | 709 | ||
731 | err: | 710 | return amdgpu_copy_buffer(ring, shadow_addr, parent_addr, |
732 | return r; | 711 | amdgpu_bo_size(shadow), NULL, fence, |
712 | true, false); | ||
733 | } | 713 | } |
734 | 714 | ||
735 | /** | 715 | /** |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 64337ff2ad63..7d3312d0da11 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | |||
@@ -273,12 +273,8 @@ int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev, | |||
273 | struct reservation_object *resv, | 273 | struct reservation_object *resv, |
274 | struct dma_fence **fence, bool direct); | 274 | struct dma_fence **fence, bool direct); |
275 | int amdgpu_bo_validate(struct amdgpu_bo *bo); | 275 | int amdgpu_bo_validate(struct amdgpu_bo *bo); |
276 | int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev, | 276 | int amdgpu_bo_restore_shadow(struct amdgpu_bo *shadow, |
277 | struct amdgpu_ring *ring, | 277 | struct dma_fence **fence); |
278 | struct amdgpu_bo *bo, | ||
279 | struct reservation_object *resv, | ||
280 | struct dma_fence **fence, | ||
281 | bool direct); | ||
282 | uint32_t amdgpu_bo_get_preferred_pin_domain(struct amdgpu_device *adev, | 278 | uint32_t amdgpu_bo_get_preferred_pin_domain(struct amdgpu_device *adev, |
283 | uint32_t domain); | 279 | uint32_t domain); |
284 | 280 | ||