diff options
author | monk.liu <monk.liu@amd.com> | 2015-07-30 03:19:05 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2015-08-17 16:50:47 -0400 |
commit | 332dfe907bef6f299f5844f947c4e141eebb8091 (patch) | |
tree | 9ff30976b2294dc4b49e4bc0b83f75a29b23dd8b /drivers/gpu/drm/amd/amdgpu | |
parent | 2e536084f24f99f0a2cc0b6ce38ad8298ea58b22 (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.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 115 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c | 3 |
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 | ||
441 | bool amdgpu_fence_signaled(struct amdgpu_fence *fence); | 441 | bool amdgpu_fence_signaled(struct amdgpu_fence *fence); |
442 | int amdgpu_fence_wait(struct amdgpu_fence *fence, bool interruptible); | 442 | int amdgpu_fence_wait(struct amdgpu_fence *fence, bool interruptible); |
443 | int amdgpu_fence_wait_any(struct amdgpu_device *adev, | 443 | signed 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); |
446 | struct amdgpu_fence *amdgpu_fence_ref(struct amdgpu_fence *fence); | 446 | struct amdgpu_fence *amdgpu_fence_ref(struct amdgpu_fence *fence); |
447 | void amdgpu_fence_unref(struct amdgpu_fence **fence); | 447 | void 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 | ||
490 | int amdgpu_user_fence_emit(struct amdgpu_ring *ring, struct amdgpu_user_fence *user, | 490 | int 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 | */ | ||
646 | int 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 | ||
1088 | static 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 | |||
1131 | struct amdgpu_wait_cb { | 1104 | struct 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 */ | ||
1159 | signed 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 | |||
1185 | const struct fence_ops amdgpu_fence_ops = { | 1214 | const 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) { |