aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-05-30 22:00:43 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-07-12 20:14:04 -0400
commit047d1d3cae2c4fc5be4fa20a97c8f5ba4fea1c56 (patch)
tree3deb5577cf97e1b9ce4f9ebb57fed56302be6e25 /drivers/gpu/drm
parentca6adb8a217fc2a6f20a50b400ba676481a90945 (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.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c31
-rw-r--r--drivers/gpu/drm/nouveau/nv04_graph.c3
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);
1111extern int nouveau_fence_flush(void *obj, void *arg); 1111extern int nouveau_fence_flush(void *obj, void *arg);
1112extern void nouveau_fence_unref(void **obj); 1112extern void nouveau_fence_unref(void **obj);
1113extern void *nouveau_fence_ref(void *obj); 1113extern void *nouveau_fence_ref(void *obj);
1114extern void nouveau_fence_handler(struct drm_device *dev, int channel);
1115 1114
1116/* nouveau_gem.c */ 1115/* nouveau_gem.c */
1117extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, 1116extern 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
89int 91int
@@ -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
224void
225nouveau_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
240int 220int
241nouveau_fence_init(struct nouveau_channel *chan) 221nouveau_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
527nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass, 527nv04_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