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>

authored by Thomas Hellstrom and committed by Dave Airlie 95ccb0f3 9a03d348

+11
+11
drivers/gpu/drm/ttm/ttm_bo.c
··· 224 int ret; 225 226 while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) { 227 if (use_sequence && bo->seq_valid && 228 (sequence - bo->val_seq < (1 << 31))) { 229 return -EAGAIN; ··· 244 } 245 246 if (use_sequence) { 247 bo->val_seq = sequence; 248 bo->seq_valid = true; 249 } else {
··· 224 int ret; 225 226 while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) { 227 + /** 228 + * Deadlock avoidance for multi-bo reserving. 229 + */ 230 if (use_sequence && bo->seq_valid && 231 (sequence - bo->val_seq < (1 << 31))) { 232 return -EAGAIN; ··· 241 } 242 243 if (use_sequence) { 244 + /** 245 + * Wake up waiters that may need to recheck for deadlock, 246 + * if we decreased the sequence number. 247 + */ 248 + if (unlikely((bo->val_seq - sequence < (1 << 31)) 249 + || !bo->seq_valid)) 250 + wake_up_all(&bo->event_queue); 251 + 252 bo->val_seq = sequence; 253 bo->seq_valid = true; 254 } else {