diff options
author | Christian König <christian.koenig@amd.com> | 2016-03-13 14:19:48 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2016-03-16 17:59:22 -0400 |
commit | c89377d10a11e5d8be11525f220dc624574c1aa5 (patch) | |
tree | 4d3fc9723c862ef28d6d88a64b5a450f0993bfe0 /drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | |
parent | e6151a08bbb3c85cd0b23813432690939e143131 (diff) |
drm/amdgpu: keep all fences in an RCU protected array v2
Just keep all HW fences in a RCU protected array as a
first step to replace the wait queue.
v2: update commit message, move fixes into separate patch.
Signed-off-by: Christian König <christian.koenig@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Chunming Zhou <david1.zhou@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c index 4654113ecfae..44eac91163eb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | |||
@@ -124,6 +124,8 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct fence **f) | |||
124 | { | 124 | { |
125 | struct amdgpu_device *adev = ring->adev; | 125 | struct amdgpu_device *adev = ring->adev; |
126 | struct amdgpu_fence *fence; | 126 | struct amdgpu_fence *fence; |
127 | struct fence *old, **ptr; | ||
128 | unsigned idx; | ||
127 | 129 | ||
128 | fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_KERNEL); | 130 | fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_KERNEL); |
129 | if (fence == NULL) | 131 | if (fence == NULL) |
@@ -137,7 +139,21 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct fence **f) | |||
137 | fence->seq); | 139 | fence->seq); |
138 | amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, | 140 | amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, |
139 | fence->seq, AMDGPU_FENCE_FLAG_INT); | 141 | fence->seq, AMDGPU_FENCE_FLAG_INT); |
142 | |||
143 | idx = fence->seq & ring->fence_drv.num_fences_mask; | ||
144 | ptr = &ring->fence_drv.fences[idx]; | ||
145 | /* This function can't be called concurrently anyway, otherwise | ||
146 | * emitting the fence would mess up the hardware ring buffer. | ||
147 | */ | ||
148 | old = rcu_dereference_protected(*ptr, 1); | ||
149 | |||
150 | rcu_assign_pointer(*ptr, fence_get(&fence->base)); | ||
151 | |||
152 | BUG_ON(old && !fence_is_signaled(old)); | ||
153 | fence_put(old); | ||
154 | |||
140 | *f = &fence->base; | 155 | *f = &fence->base; |
156 | |||
141 | return 0; | 157 | return 0; |
142 | } | 158 | } |
143 | 159 | ||
@@ -380,6 +396,11 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring, | |||
380 | (unsigned long)ring); | 396 | (unsigned long)ring); |
381 | 397 | ||
382 | init_waitqueue_head(&ring->fence_drv.fence_queue); | 398 | init_waitqueue_head(&ring->fence_drv.fence_queue); |
399 | ring->fence_drv.num_fences_mask = num_hw_submission - 1; | ||
400 | ring->fence_drv.fences = kcalloc(num_hw_submission, sizeof(void *), | ||
401 | GFP_KERNEL); | ||
402 | if (!ring->fence_drv.fences) | ||
403 | return -ENOMEM; | ||
383 | 404 | ||
384 | timeout = msecs_to_jiffies(amdgpu_lockup_timeout); | 405 | timeout = msecs_to_jiffies(amdgpu_lockup_timeout); |
385 | if (timeout == 0) { | 406 | if (timeout == 0) { |
@@ -441,10 +462,9 @@ int amdgpu_fence_driver_init(struct amdgpu_device *adev) | |||
441 | */ | 462 | */ |
442 | void amdgpu_fence_driver_fini(struct amdgpu_device *adev) | 463 | void amdgpu_fence_driver_fini(struct amdgpu_device *adev) |
443 | { | 464 | { |
444 | int i, r; | 465 | unsigned i, j; |
466 | int r; | ||
445 | 467 | ||
446 | if (atomic_dec_and_test(&amdgpu_fence_slab_ref)) | ||
447 | kmem_cache_destroy(amdgpu_fence_slab); | ||
448 | for (i = 0; i < AMDGPU_MAX_RINGS; i++) { | 468 | for (i = 0; i < AMDGPU_MAX_RINGS; i++) { |
449 | struct amdgpu_ring *ring = adev->rings[i]; | 469 | struct amdgpu_ring *ring = adev->rings[i]; |
450 | 470 | ||
@@ -460,8 +480,14 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev) | |||
460 | ring->fence_drv.irq_type); | 480 | ring->fence_drv.irq_type); |
461 | amd_sched_fini(&ring->sched); | 481 | amd_sched_fini(&ring->sched); |
462 | del_timer_sync(&ring->fence_drv.fallback_timer); | 482 | del_timer_sync(&ring->fence_drv.fallback_timer); |
483 | for (j = 0; j <= ring->fence_drv.num_fences_mask; ++j) | ||
484 | fence_put(ring->fence_drv.fences[i]); | ||
485 | kfree(ring->fence_drv.fences); | ||
463 | ring->fence_drv.initialized = false; | 486 | ring->fence_drv.initialized = false; |
464 | } | 487 | } |
488 | |||
489 | if (atomic_dec_and_test(&amdgpu_fence_slab_ref)) | ||
490 | kmem_cache_destroy(amdgpu_fence_slab); | ||
465 | } | 491 | } |
466 | 492 | ||
467 | /** | 493 | /** |