diff options
author | Francisco Jerez <currojerez@riseup.net> | 2010-08-28 11:56:33 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-09-02 18:23:30 -0400 |
commit | 3ba6462355c1c69dde58739a871d13bbb993e2e3 (patch) | |
tree | 040d1f821170f170e9b6af4d91d86e5fbfca13d1 /drivers/gpu | |
parent | ab699ec64a4294f2f6ccd34b9bf8a2dcb4c4cb3c (diff) |
drm/nouveau: Take fence spinlock before reading the last sequence.
It fixes a race between the TTM delayed work queue and the GEM IOCTLs
(fdo bug 29583) uncovered by the BKL removal.
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fence.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 6b208ffafa8d..87ac21ec23d2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c | |||
@@ -64,16 +64,17 @@ nouveau_fence_update(struct nouveau_channel *chan) | |||
64 | struct nouveau_fence *fence; | 64 | struct nouveau_fence *fence; |
65 | uint32_t sequence; | 65 | uint32_t sequence; |
66 | 66 | ||
67 | spin_lock(&chan->fence.lock); | ||
68 | |||
67 | if (USE_REFCNT) | 69 | if (USE_REFCNT) |
68 | sequence = nvchan_rd32(chan, 0x48); | 70 | sequence = nvchan_rd32(chan, 0x48); |
69 | else | 71 | else |
70 | sequence = atomic_read(&chan->fence.last_sequence_irq); | 72 | sequence = atomic_read(&chan->fence.last_sequence_irq); |
71 | 73 | ||
72 | if (chan->fence.sequence_ack == sequence) | 74 | if (chan->fence.sequence_ack == sequence) |
73 | return; | 75 | goto out; |
74 | chan->fence.sequence_ack = sequence; | 76 | chan->fence.sequence_ack = sequence; |
75 | 77 | ||
76 | spin_lock(&chan->fence.lock); | ||
77 | list_for_each_safe(entry, tmp, &chan->fence.pending) { | 78 | list_for_each_safe(entry, tmp, &chan->fence.pending) { |
78 | fence = list_entry(entry, struct nouveau_fence, entry); | 79 | fence = list_entry(entry, struct nouveau_fence, entry); |
79 | 80 | ||
@@ -85,6 +86,7 @@ nouveau_fence_update(struct nouveau_channel *chan) | |||
85 | if (sequence == chan->fence.sequence_ack) | 86 | if (sequence == chan->fence.sequence_ack) |
86 | break; | 87 | break; |
87 | } | 88 | } |
89 | out: | ||
88 | spin_unlock(&chan->fence.lock); | 90 | spin_unlock(&chan->fence.lock); |
89 | } | 91 | } |
90 | 92 | ||