aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJerome Glisse <jglisse@redhat.com>2012-05-09 09:34:47 -0400
committerDave Airlie <airlied@redhat.com>2012-05-09 12:22:19 -0400
commit3b7a2b24ea2b703b3af595d0d4ee233ab0b36377 (patch)
tree0f8ccea66571d7ffa556dd55cf8717e429ed59cf
parentbb635567291482a87e4cc46e6683419c1f365ddf (diff)
drm/radeon: rework fence handling, drop fence list v7
Using 64bits fence sequence we can directly compare sequence number to know if a fence is signaled or not. Thus the fence list became useless, so does the fence lock that mainly protected the fence list. Things like ring.ready are no longer behind a lock, this should be ok as ring.ready is initialized once and will only change when facing lockup. Worst case is that we return an -EBUSY just after a successfull GPU reset, or we go into wait state instead of returning -EBUSY (thus delaying reporting -EBUSY to fence wait caller). v2: Remove left over comment, force using writeback on cayman and newer, thus not having to suffer from possibly scratch reg exhaustion v3: Rebase on top of change to uint64 fence patch v4: Change DCE5 test to force write back on cayman and newer but also any APU such as PALM or SUMO family v5: Rebase on top of new uint64 fence patch v6: Just break if seq doesn't change any more. Use radeon_fence prefix for all function names. Even if it's now highly optimized, try avoiding polling to often. v7: We should never poll the last_seq from the hardware without waking the sleeping threads, otherwise we might lose events. Signed-off-by: Jerome Glisse <jglisse@redhat.com> Signed-off-by: Christian König <deathsimple@vodafone.de> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/radeon/radeon.h6
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c8
-rw-r--r--drivers/gpu/drm/radeon/radeon_fence.c299
3 files changed, 119 insertions, 194 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index cdf46bc6dcc4..7c8711793421 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -263,15 +263,12 @@ struct radeon_fence_driver {
263 atomic64_t last_seq; 263 atomic64_t last_seq;
264 unsigned long last_activity; 264 unsigned long last_activity;
265 wait_queue_head_t queue; 265 wait_queue_head_t queue;
266 struct list_head emitted;
267 struct list_head signaled;
268 bool initialized; 266 bool initialized;
269}; 267};
270 268
271struct radeon_fence { 269struct radeon_fence {
272 struct radeon_device *rdev; 270 struct radeon_device *rdev;
273 struct kref kref; 271 struct kref kref;
274 struct list_head list;
275 /* protected by radeon_fence.lock */ 272 /* protected by radeon_fence.lock */
276 uint64_t seq; 273 uint64_t seq;
277 /* RB, DMA, etc. */ 274 /* RB, DMA, etc. */
@@ -291,7 +288,7 @@ int radeon_fence_wait_next(struct radeon_device *rdev, int ring);
291int radeon_fence_wait_empty(struct radeon_device *rdev, int ring); 288int radeon_fence_wait_empty(struct radeon_device *rdev, int ring);
292struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence); 289struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
293void radeon_fence_unref(struct radeon_fence **fence); 290void radeon_fence_unref(struct radeon_fence **fence);
294int radeon_fence_count_emitted(struct radeon_device *rdev, int ring); 291unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring);
295 292
296/* 293/*
297 * Tiling registers 294 * Tiling registers
@@ -1534,7 +1531,6 @@ struct radeon_device {
1534 struct radeon_mode_info mode_info; 1531 struct radeon_mode_info mode_info;
1535 struct radeon_scratch scratch; 1532 struct radeon_scratch scratch;
1536 struct radeon_mman mman; 1533 struct radeon_mman mman;
1537 rwlock_t fence_lock;
1538 struct radeon_fence_driver fence_drv[RADEON_NUM_RINGS]; 1534 struct radeon_fence_driver fence_drv[RADEON_NUM_RINGS];
1539 struct radeon_semaphore_driver semaphore_drv; 1535 struct radeon_semaphore_driver semaphore_drv;
1540 struct mutex ring_lock; 1536 struct mutex ring_lock;
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 3f6ff2a0bce2..0e7b72a0ed35 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -225,9 +225,9 @@ int radeon_wb_init(struct radeon_device *rdev)
225 /* disable event_write fences */ 225 /* disable event_write fences */
226 rdev->wb.use_event = false; 226 rdev->wb.use_event = false;
227 /* disabled via module param */ 227 /* disabled via module param */
228 if (radeon_no_wb == 1) 228 if (radeon_no_wb == 1) {
229 rdev->wb.enabled = false; 229 rdev->wb.enabled = false;
230 else { 230 } else {
231 if (rdev->flags & RADEON_IS_AGP) { 231 if (rdev->flags & RADEON_IS_AGP) {
232 /* often unreliable on AGP */ 232 /* often unreliable on AGP */
233 rdev->wb.enabled = false; 233 rdev->wb.enabled = false;
@@ -237,8 +237,9 @@ int radeon_wb_init(struct radeon_device *rdev)
237 } else { 237 } else {
238 rdev->wb.enabled = true; 238 rdev->wb.enabled = true;
239 /* event_write fences are only available on r600+ */ 239 /* event_write fences are only available on r600+ */
240 if (rdev->family >= CHIP_R600) 240 if (rdev->family >= CHIP_R600) {
241 rdev->wb.use_event = true; 241 rdev->wb.use_event = true;
242 }
242 } 243 }
243 } 244 }
244 /* always use writeback/events on NI, APUs */ 245 /* always use writeback/events on NI, APUs */
@@ -731,7 +732,6 @@ int radeon_device_init(struct radeon_device *rdev,
731 mutex_init(&rdev->gem.mutex); 732 mutex_init(&rdev->gem.mutex);
732 mutex_init(&rdev->pm.mutex); 733 mutex_init(&rdev->pm.mutex);
733 mutex_init(&rdev->vram_mutex); 734 mutex_init(&rdev->vram_mutex);
734 rwlock_init(&rdev->fence_lock);
735 rwlock_init(&rdev->semaphore_drv.lock); 735 rwlock_init(&rdev->semaphore_drv.lock);
736 INIT_LIST_HEAD(&rdev->gem.objects); 736 INIT_LIST_HEAD(&rdev->gem.objects);
737 init_waitqueue_head(&rdev->irq.vblank_queue); 737 init_waitqueue_head(&rdev->irq.vblank_queue);
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index feb2bbc6ef6d..ed202255ac76 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -63,30 +63,18 @@ static u32 radeon_fence_read(struct radeon_device *rdev, int ring)
63 63
64int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) 64int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)
65{ 65{
66 unsigned long irq_flags; 66 /* we are protected by the ring emission mutex */
67
68 write_lock_irqsave(&rdev->fence_lock, irq_flags);
69 if (fence->seq && fence->seq < RADEON_FENCE_NOTEMITED_SEQ) { 67 if (fence->seq && fence->seq < RADEON_FENCE_NOTEMITED_SEQ) {
70 write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
71 return 0; 68 return 0;
72 } 69 }
73 /* we are protected by the ring emission mutex */
74 fence->seq = ++rdev->fence_drv[fence->ring].seq; 70 fence->seq = ++rdev->fence_drv[fence->ring].seq;
75 radeon_fence_ring_emit(rdev, fence->ring, fence); 71 radeon_fence_ring_emit(rdev, fence->ring, fence);
76 trace_radeon_fence_emit(rdev->ddev, fence->seq); 72 trace_radeon_fence_emit(rdev->ddev, fence->seq);
77 /* are we the first fence on a previusly idle ring? */
78 if (list_empty(&rdev->fence_drv[fence->ring].emitted)) {
79 rdev->fence_drv[fence->ring].last_activity = jiffies;
80 }
81 list_move_tail(&fence->list, &rdev->fence_drv[fence->ring].emitted);
82 write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
83 return 0; 73 return 0;
84} 74}
85 75
86static bool radeon_fence_poll_locked(struct radeon_device *rdev, int ring) 76void radeon_fence_process(struct radeon_device *rdev, int ring)
87{ 77{
88 struct radeon_fence *fence;
89 struct list_head *i, *n;
90 uint64_t seq, last_seq; 78 uint64_t seq, last_seq;
91 unsigned count_loop = 0; 79 unsigned count_loop = 0;
92 bool wake = false; 80 bool wake = false;
@@ -120,14 +108,15 @@ static bool radeon_fence_poll_locked(struct radeon_device *rdev, int ring)
120 seq += 0x100000000LL; 108 seq += 0x100000000LL;
121 } 109 }
122 110
123 if (!wake && seq == last_seq) { 111 if (seq == last_seq) {
124 return false; 112 break;
125 } 113 }
126 /* If we loop over we don't want to return without 114 /* If we loop over we don't want to return without
127 * checking if a fence is signaled as it means that the 115 * checking if a fence is signaled as it means that the
128 * seq we just read is different from the previous on. 116 * seq we just read is different from the previous on.
129 */ 117 */
130 wake = true; 118 wake = true;
119 last_seq = seq;
131 if ((count_loop++) > 10) { 120 if ((count_loop++) > 10) {
132 /* We looped over too many time leave with the 121 /* We looped over too many time leave with the
133 * fact that we might have set an older fence 122 * fact that we might have set an older fence
@@ -136,46 +125,20 @@ static bool radeon_fence_poll_locked(struct radeon_device *rdev, int ring)
136 */ 125 */
137 break; 126 break;
138 } 127 }
139 last_seq = seq;
140 } while (atomic64_xchg(&rdev->fence_drv[ring].last_seq, seq) > seq); 128 } while (atomic64_xchg(&rdev->fence_drv[ring].last_seq, seq) > seq);
141 129
142 /* reset wake to false */ 130 if (wake) {
143 wake = false; 131 rdev->fence_drv[ring].last_activity = jiffies;
144 rdev->fence_drv[ring].last_activity = jiffies; 132 wake_up_all(&rdev->fence_drv[ring].queue);
145
146 n = NULL;
147 list_for_each(i, &rdev->fence_drv[ring].emitted) {
148 fence = list_entry(i, struct radeon_fence, list);
149 if (fence->seq == seq) {
150 n = i;