aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/ttm
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2010-11-11 04:04:53 -0500
committerDave Airlie <airlied@redhat.com>2010-11-18 00:00:42 -0500
commit95ccb0f3bdc4438bf470c25450e6a8a6090ca253 (patch)
treea4a55496a9483ddf43d8bd72c149341536628874 /drivers/gpu/drm/ttm
parent9a03d3487abe89e3650bb2533c5d909143955499 (diff)
drm/ttm: Fix up a theoretical deadlock
A process suspended waiting for a higher sequence or no sequence to unreserve, a bo may be beaten to the reservation by a process with a lower sequence. In that case the first process should give up trying to reserve and return -EAGAIN. In order for that to happen, we must wake waiting processes when we change sequence, so that they have a chance to detect the new sequence. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/ttm')
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 3ca77dc03915..148a322d8f5d 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -224,6 +224,9 @@ int ttm_bo_reserve_locked(struct ttm_buffer_object *bo,
224 int ret; 224 int ret;
225 225
226 while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) { 226 while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) {
227 /**
228 * Deadlock avoidance for multi-bo reserving.
229 */
227 if (use_sequence && bo->seq_valid && 230 if (use_sequence && bo->seq_valid &&
228 (sequence - bo->val_seq < (1 << 31))) { 231 (sequence - bo->val_seq < (1 << 31))) {
229 return -EAGAIN; 232 return -EAGAIN;
@@ -241,6 +244,14 @@ int ttm_bo_reserve_locked(struct ttm_buffer_object *bo,
241 } 244 }
242 245
243 if (use_sequence) { 246 if (use_sequence) {
247 /**
248 * Wake up waiters that may need to recheck for deadlock,
249 * if we decreased the sequence number.
250 */
251 if (unlikely((bo->val_seq - sequence < (1 << 31))
252 || !bo->seq_valid))
253 wake_up_all(&bo->event_queue);
254
244 bo->val_seq = sequence; 255 bo->val_seq = sequence;
245 bo->seq_valid = true; 256 bo->seq_valid = true;
246 } else { 257 } else {