diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2010-05-30 22:00:43 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-07-12 20:14:04 -0400 |
commit | 047d1d3cae2c4fc5be4fa20a97c8f5ba4fea1c56 (patch) | |
tree | 3deb5577cf97e1b9ce4f9ebb57fed56302be6e25 /drivers/gpu/drm | |
parent | ca6adb8a217fc2a6f20a50b400ba676481a90945 (diff) |
drm/nouveau: reduce usage of fence spinlock to when absolutely necessary
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_channel.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fence.c | 31 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv04_graph.c | 3 |
4 files changed, 8 insertions, 31 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 53daeba4581e..90fdcda332be 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c | |||
@@ -258,9 +258,7 @@ nouveau_channel_free(struct nouveau_channel *chan) | |||
258 | nouveau_debugfs_channel_fini(chan); | 258 | nouveau_debugfs_channel_fini(chan); |
259 | 259 | ||
260 | /* Give outstanding push buffers a chance to complete */ | 260 | /* Give outstanding push buffers a chance to complete */ |
261 | spin_lock_irqsave(&chan->fence.lock, flags); | ||
262 | nouveau_fence_update(chan); | 261 | nouveau_fence_update(chan); |
263 | spin_unlock_irqrestore(&chan->fence.lock, flags); | ||
264 | if (chan->fence.sequence != chan->fence.sequence_ack) { | 262 | if (chan->fence.sequence != chan->fence.sequence_ack) { |
265 | struct nouveau_fence *fence = NULL; | 263 | struct nouveau_fence *fence = NULL; |
266 | 264 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 47fa28ddec75..587a0ab1fe67 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -188,7 +188,7 @@ struct nouveau_channel { | |||
188 | struct list_head pending; | 188 | struct list_head pending; |
189 | uint32_t sequence; | 189 | uint32_t sequence; |
190 | uint32_t sequence_ack; | 190 | uint32_t sequence_ack; |
191 | uint32_t last_sequence_irq; | 191 | atomic_t last_sequence_irq; |
192 | } fence; | 192 | } fence; |
193 | 193 | ||
194 | /* DMA push buffer */ | 194 | /* DMA push buffer */ |
@@ -1111,7 +1111,6 @@ extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); | |||
1111 | extern int nouveau_fence_flush(void *obj, void *arg); | 1111 | extern int nouveau_fence_flush(void *obj, void *arg); |
1112 | extern void nouveau_fence_unref(void **obj); | 1112 | extern void nouveau_fence_unref(void **obj); |
1113 | extern void *nouveau_fence_ref(void *obj); | 1113 | extern void *nouveau_fence_ref(void *obj); |
1114 | extern void nouveau_fence_handler(struct drm_device *dev, int channel); | ||
1115 | 1114 | ||
1116 | /* nouveau_gem.c */ | 1115 | /* nouveau_gem.c */ |
1117 | extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, | 1116 | extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index faddf53ff9ed..813d853b741b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c | |||
@@ -67,12 +67,13 @@ nouveau_fence_update(struct nouveau_channel *chan) | |||
67 | if (USE_REFCNT) | 67 | if (USE_REFCNT) |
68 | sequence = nvchan_rd32(chan, 0x48); | 68 | sequence = nvchan_rd32(chan, 0x48); |
69 | else | 69 | else |
70 | sequence = chan->fence.last_sequence_irq; | 70 | sequence = atomic_read(&chan->fence.last_sequence_irq); |
71 | 71 | ||
72 | if (chan->fence.sequence_ack == sequence) | 72 | if (chan->fence.sequence_ack == sequence) |
73 | return; | 73 | return; |
74 | chan->fence.sequence_ack = sequence; | 74 | chan->fence.sequence_ack = sequence; |
75 | 75 | ||
76 | spin_lock(&chan->fence.lock); | ||
76 | list_for_each_safe(entry, tmp, &chan->fence.pending) { | 77 | list_for_each_safe(entry, tmp, &chan->fence.pending) { |
77 | fence = list_entry(entry, struct nouveau_fence, entry); | 78 | fence = list_entry(entry, struct nouveau_fence, entry); |
78 | 79 | ||
@@ -84,6 +85,7 @@ nouveau_fence_update(struct nouveau_channel *chan) | |||
84 | if (sequence == chan->fence.sequence_ack) | 85 | if (sequence == chan->fence.sequence_ack) |
85 | break; | 86 | break; |
86 | } | 87 | } |
88 | spin_unlock(&chan->fence.lock); | ||
87 | } | 89 | } |
88 | 90 | ||
89 | int | 91 | int |
@@ -119,7 +121,6 @@ nouveau_fence_emit(struct nouveau_fence *fence) | |||
119 | { | 121 | { |
120 | struct drm_nouveau_private *dev_priv = fence->channel->dev->dev_private; | 122 | struct drm_nouveau_private *dev_priv = fence->channel->dev->dev_private; |
121 | struct nouveau_channel *chan = fence->channel; | 123 | struct nouveau_channel *chan = fence->channel; |
122 | unsigned long flags; | ||
123 | int ret; | 124 | int ret; |
124 | 125 | ||
125 | ret = RING_SPACE(chan, 2); | 126 | ret = RING_SPACE(chan, 2); |
@@ -127,9 +128,7 @@ nouveau_fence_emit(struct nouveau_fence *fence) | |||
127 | return ret; | 128 | return ret; |
128 | 129 | ||
129 | if (unlikely(chan->fence.sequence == chan->fence.sequence_ack - 1)) { | 130 | if (unlikely(chan->fence.sequence == chan->fence.sequence_ack - 1)) { |
130 | spin_lock_irqsave(&chan->fence.lock, flags); | ||
131 | nouveau_fence_update(chan); | 131 | nouveau_fence_update(chan); |
132 | spin_unlock_irqrestore(&chan->fence.lock, flags); | ||
133 | 132 | ||
134 | BUG_ON(chan->fence.sequence == | 133 | BUG_ON(chan->fence.sequence == |
135 | chan->fence.sequence_ack - 1); | 134 | chan->fence.sequence_ack - 1); |
@@ -138,9 +137,9 @@ nouveau_fence_emit(struct nouveau_fence *fence) | |||
138 | fence->sequence = ++chan->fence.sequence; | 137 | fence->sequence = ++chan->fence.sequence; |
139 | 138 | ||
140 | kref_get(&fence->refcount); | 139 | kref_get(&fence->refcount); |
141 | spin_lock_irqsave(&chan->fence.lock, flags); | 140 | spin_lock(&chan->fence.lock); |
142 | list_add_tail(&fence->entry, &chan->fence.pending); | 141 | list_add_tail(&fence->entry, &chan->fence.pending); |
143 | spin_unlock_irqrestore(&chan->fence.lock, flags); | 142 | spin_unlock(&chan->fence.lock); |
144 | 143 | ||
145 | BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1); | 144 | BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1); |
146 | OUT_RING(chan, fence->sequence); | 145 | OUT_RING(chan, fence->sequence); |
@@ -173,14 +172,11 @@ nouveau_fence_signalled(void *sync_obj, void *sync_arg) | |||
173 | { | 172 | { |
174 | struct nouveau_fence *fence = nouveau_fence(sync_obj); | 173 | struct nouveau_fence *fence = nouveau_fence(sync_obj); |
175 | struct nouveau_channel *chan = fence->channel; | 174 | struct nouveau_channel *chan = fence->channel; |
176 | unsigned long flags; | ||
177 | 175 | ||
178 | if (fence->signalled) | 176 | if (fence->signalled) |
179 | return true; | 177 | return true; |
180 | 178 | ||
181 | spin_lock_irqsave(&chan->fence.lock, flags); | ||
182 | nouveau_fence_update(chan); | 179 | nouveau_fence_update(chan); |
183 | spin_unlock_irqrestore(&chan->fence.lock, flags); | ||
184 | return fence->signalled; | 180 | return fence->signalled; |
185 | } | 181 | } |
186 | 182 | ||
@@ -221,27 +217,12 @@ nouveau_fence_flush(void *sync_obj, void *sync_arg) | |||
221 | return 0; | 217 | return 0; |
222 | } | 218 | } |
223 | 219 | ||
224 | void | ||
225 | nouveau_fence_handler(struct drm_device *dev, int channel) | ||
226 | { | ||
227 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
228 | struct nouveau_channel *chan = NULL; | ||
229 | |||
230 | if (channel >= 0 && channel < dev_priv->engine.fifo.channels) | ||
231 | chan = dev_priv->fifos[channel]; | ||
232 | |||
233 | if (chan) { | ||
234 | spin_lock_irq(&chan->fence.lock); | ||
235 | nouveau_fence_update(chan); | ||
236 | spin_unlock_irq(&chan->fence.lock); | ||
237 | } | ||
238 | } | ||
239 | |||
240 | int | 220 | int |
241 | nouveau_fence_init(struct nouveau_channel *chan) | 221 | nouveau_fence_init(struct nouveau_channel *chan) |
242 | { | 222 | { |
243 | INIT_LIST_HEAD(&chan->fence.pending); | 223 | INIT_LIST_HEAD(&chan->fence.pending); |
244 | spin_lock_init(&chan->fence.lock); | 224 | spin_lock_init(&chan->fence.lock); |
225 | atomic_set(&chan->fence.last_sequence_irq, 0); | ||
245 | return 0; | 226 | return 0; |
246 | } | 227 | } |
247 | 228 | ||
diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c index dd09679d31dc..c8973421b635 100644 --- a/drivers/gpu/drm/nouveau/nv04_graph.c +++ b/drivers/gpu/drm/nouveau/nv04_graph.c | |||
@@ -527,8 +527,7 @@ static int | |||
527 | nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass, | 527 | nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass, |
528 | int mthd, uint32_t data) | 528 | int mthd, uint32_t data) |
529 | { | 529 | { |
530 | chan->fence.last_sequence_irq = data; | 530 | atomic_set(&chan->fence.last_sequence_irq, data); |
531 | nouveau_fence_handler(chan->dev, chan->id); | ||
532 | return 0; | 531 | return 0; |
533 | } | 532 | } |
534 | 533 | ||