aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu
diff options
context:
space:
mode:
authormonk.liu <monk.liu@amd.com>2015-07-30 03:19:05 -0400
committerAlex Deucher <alexander.deucher@amd.com>2015-08-17 16:50:47 -0400
commit332dfe907bef6f299f5844f947c4e141eebb8091 (patch)
tree9ff30976b2294dc4b49e4bc0b83f75a29b23dd8b /drivers/gpu/drm/amd/amdgpu
parent2e536084f24f99f0a2cc0b6ce38ad8298ea58b22 (diff)
drm/amdgpu: new implement for fence_wait_any (v2)
origninal method will sleep/schedule at the granurarity of HZ/2 and based on seq signal method, the new implement is based on kernel fance interface, no unnecessary schedule at all v2: replace logic of original amdgpu_fence_wait_any Signed-off-by: monk.liu <monk.liu@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c115
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c3
3 files changed, 77 insertions, 47 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 1e87acf35892..5f32f859230b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -440,9 +440,9 @@ unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring);
440 440
441bool amdgpu_fence_signaled(struct amdgpu_fence *fence); 441bool amdgpu_fence_signaled(struct amdgpu_fence *fence);
442int amdgpu_fence_wait(struct amdgpu_fence *fence, bool interruptible); 442int amdgpu_fence_wait(struct amdgpu_fence *fence, bool interruptible);
443int amdgpu_fence_wait_any(struct amdgpu_device *adev, 443signed long amdgpu_fence_wait_any(struct amdgpu_device *adev,
444 struct amdgpu_fence **fences, 444 struct amdgpu_fence **fences,
445 bool intr); 445 bool intr, long t);
446struct amdgpu_fence *amdgpu_fence_ref(struct amdgpu_fence *fence); 446struct amdgpu_fence *amdgpu_fence_ref(struct amdgpu_fence *fence);
447void amdgpu_fence_unref(struct amdgpu_fence **fence); 447void amdgpu_fence_unref(struct amdgpu_fence **fence);
448 448
@@ -487,7 +487,7 @@ static inline bool amdgpu_fence_is_earlier(struct amdgpu_fence *a,
487 return a->seq < b->seq; 487 return a->seq < b->seq;
488} 488}
489 489
490int amdgpu_user_fence_emit(struct amdgpu_ring *ring, struct amdgpu_user_fence *user, 490int amdgpu_user_fence_emit(struct amdgpu_ring *ring, struct amdgpu_user_fence *user,
491 void *owner, struct amdgpu_fence **fence); 491 void *owner, struct amdgpu_fence **fence);
492 492
493/* 493/*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
index 4834725b627e..a4982f53f937 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -631,49 +631,6 @@ int amdgpu_fence_wait(struct amdgpu_fence *fence, bool intr)
631} 631}
632 632
633/** 633/**
634 * amdgpu_fence_wait_any - wait for a fence to signal on any ring
635 *
636 * @adev: amdgpu device pointer
637 * @fences: amdgpu fence object(s)
638 * @intr: use interruptable sleep
639 *
640 * Wait for any requested fence to signal (all asics). Fence
641 * array is indexed by ring id. @intr selects whether to use
642 * interruptable (true) or non-interruptable (false) sleep when
643 * waiting for the fences. Used by the suballocator.
644 * Returns 0 if any fence has passed, error for all other cases.
645 */
646int amdgpu_fence_wait_any(struct amdgpu_device *adev,
647 struct amdgpu_fence **fences,
648 bool intr)
649{
650 uint64_t seq[AMDGPU_MAX_RINGS];
651 unsigned i, num_rings = 0;
652 long r;
653
654 for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
655 seq[i] = 0;
656
657 if (!fences[i]) {
658 continue;
659 }
660
661 seq[i] = fences[i]->seq;
662 ++num_rings;
663 }
664
665 /* nothing to wait for ? */
666 if (num_rings == 0)
667 return -ENOENT;
668
669 r = amdgpu_fence_wait_seq_timeout(adev, seq, intr, MAX_SCHEDULE_TIMEOUT);
670 if (r < 0) {
671 return r;
672 }
673 return 0;
674}
675
676/**
677 * amdgpu_fence_wait_next - wait for the next fence to signal 634 * amdgpu_fence_wait_next - wait for the next fence to signal
678 * 635 *
679 * @adev: amdgpu device pointer 636 * @adev: amdgpu device pointer
@@ -1128,6 +1085,22 @@ static inline bool amdgpu_test_signaled(struct amdgpu_fence *fence)
1128 return test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags); 1085 return test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags);
1129} 1086}
1130 1087
1088static inline bool amdgpu_test_signaled_any(struct amdgpu_fence **fences)
1089{
1090 int idx;
1091 struct amdgpu_fence *fence;
1092
1093 idx = 0;
1094 for (idx = 0; idx < AMDGPU_MAX_RINGS; ++idx) {
1095 fence = fences[idx];
1096 if (fence) {
1097 if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags))
1098 return true;
1099 }
1100 }
1101 return false;
1102}
1103
1131struct amdgpu_wait_cb { 1104struct amdgpu_wait_cb {
1132 struct fence_cb base; 1105 struct fence_cb base;
1133 struct task_struct *task; 1106 struct task_struct *task;
@@ -1182,6 +1155,62 @@ static signed long amdgpu_fence_default_wait(struct fence *f, bool intr,
1182 return t; 1155 return t;
1183} 1156}
1184 1157
1158/* wait until any fence in array signaled */
1159signed long amdgpu_fence_wait_any(struct amdgpu_device *adev,
1160 struct amdgpu_fence **array, bool intr, signed long t)
1161{
1162 long idx = 0;
1163 struct amdgpu_wait_cb cb[AMDGPU_MAX_RINGS];
1164 struct amdgpu_fence *fence;
1165
1166 BUG_ON(!array);
1167
1168 for (idx = 0; idx < AMDGPU_MAX_RINGS; ++idx) {
1169 fence = array[idx];
1170 if (fence) {
1171 cb[idx].task = current;
1172 if (fence_add_callback(&fence->base,
1173 &cb[idx].base, amdgpu_fence_wait_cb))
1174 return t; /* return if fence is already signaled */
1175 }
1176 }
1177
1178 while (t > 0) {
1179 if (intr)
1180 set_current_state(TASK_INTERRUPTIBLE);
1181 else
1182 set_current_state(TASK_UNINTERRUPTIBLE);
1183
1184 /*
1185 * amdgpu_test_signaled_any must be called after
1186 * set_current_state to prevent a race with wake_up_process
1187 */
1188 if (amdgpu_test_signaled_any(array))
1189 break;
1190
1191 if (adev->needs_reset) {
1192 t = -EDEADLK;
1193 break;
1194 }
1195
1196 t = schedule_timeout(t);
1197
1198 if (t > 0 && intr && signal_pending(current))
1199 t = -ERESTARTSYS;
1200 }
1201
1202 __set_current_state(TASK_RUNNING);
1203
1204 idx = 0;
1205 for (idx = 0; idx < AMDGPU_MAX_RINGS; ++idx) {
1206 fence = array[idx];
1207 if (fence)
1208 fence_remove_callback(&fence->base, &cb[idx].base);
1209 }
1210
1211 return t;
1212}
1213
1185const struct fence_ops amdgpu_fence_ops = { 1214const struct fence_ops amdgpu_fence_ops = {
1186 .get_driver_name = amdgpu_fence_get_driver_name, 1215 .get_driver_name = amdgpu_fence_get_driver_name,
1187 .get_timeline_name = amdgpu_fence_get_timeline_name, 1216 .get_timeline_name = amdgpu_fence_get_timeline_name,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
index eb20987ce18d..f4e20eaede82 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
@@ -350,7 +350,8 @@ int amdgpu_sa_bo_new(struct amdgpu_device *adev,
350 } while (amdgpu_sa_bo_next_hole(sa_manager, fences, tries)); 350 } while (amdgpu_sa_bo_next_hole(sa_manager, fences, tries));
351 351
352 spin_unlock(&sa_manager->wq.lock); 352 spin_unlock(&sa_manager->wq.lock);
353 r = amdgpu_fence_wait_any(adev, fences, false); 353 r = amdgpu_fence_wait_any(adev, fences, false, MAX_SCHEDULE_TIMEOUT);
354 r = (r > 0) ? 0 : r;
354 spin_lock(&sa_manager->wq.lock); 355 spin_lock(&sa_manager->wq.lock);
355 /* if we have nothing to wait for block */ 356 /* if we have nothing to wait for block */
356 if (r == -ENOENT) { 357 if (r == -ENOENT) {