aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_fence.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-04-29 23:30:00 -0400
committerBen Skeggs <bskeggs@redhat.com>2012-05-24 02:55:46 -0400
commitd375e7d56dffa564a6c337d2ed3217fb94826100 (patch)
treeddce2af34f6c0eee35cb3b5c99cd1707d6b63ae4 /drivers/gpu/drm/nouveau/nouveau_fence.c
parent875ac34aad49bb875833aed2b4f2deb7a28df9f0 (diff)
drm/nouveau/fence: minor api changes for an upcoming rework
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_fence.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c215
1 files changed, 85 insertions, 130 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index f26177ac27e7..2c10d54fc493 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -32,47 +32,13 @@
32 32
33#include "nouveau_drv.h" 33#include "nouveau_drv.h"
34#include "nouveau_ramht.h" 34#include "nouveau_ramht.h"
35#include "nouveau_fence.h"
35#include "nouveau_software.h" 36#include "nouveau_software.h"
36#include "nouveau_dma.h" 37#include "nouveau_dma.h"
37 38
38#define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10) 39#define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10)
39#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17) 40#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17)
40 41
41struct nouveau_fence {
42 struct nouveau_channel *channel;
43 struct kref refcount;
44 struct list_head entry;
45
46 uint32_t sequence;
47 bool signalled;
48 unsigned long timeout;
49
50 void (*work)(void *priv, bool signalled);
51 void *priv;
52};
53
54struct nouveau_semaphore {
55 struct kref ref;
56 struct drm_device *dev;
57 struct drm_mm_node *mem;
58};
59
60static inline struct nouveau_fence *
61nouveau_fence(void *sync_obj)
62{
63 return (struct nouveau_fence *)sync_obj;
64}
65
66static void
67nouveau_fence_del(struct kref *ref)
68{
69 struct nouveau_fence *fence =
70 container_of(ref, struct nouveau_fence, refcount);
71
72 nouveau_channel_ref(NULL, &fence->channel);
73 kfree(fence);
74}
75
76void 42void
77nouveau_fence_update(struct nouveau_channel *chan) 43nouveau_fence_update(struct nouveau_channel *chan)
78{ 44{
@@ -94,16 +60,16 @@ nouveau_fence_update(struct nouveau_channel *chan)
94 chan->fence.sequence_ack = sequence; 60 chan->fence.sequence_ack = sequence;
95 } 61 }
96 62
97 list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { 63 list_for_each_entry_safe(fence, tmp, &chan->fence.pending, head) {
98 if (fence->sequence > chan->fence.sequence_ack) 64 if (fence->sequence > chan->fence.sequence_ack)
99 break; 65 break;
100 66
101 fence->signalled = true; 67 fence->channel = NULL;
102 list_del(&fence->entry); 68 list_del(&fence->head);
103 if (fence->work) 69 if (fence->work)
104 fence->work(fence->priv, true); 70 fence->work(fence->priv, true);
105 71
106 kref_put(&fence->refcount, nouveau_fence_del); 72 nouveau_fence_unref(&fence);
107 } 73 }
108 74
109out: 75out:
@@ -111,37 +77,8 @@ out:
111} 77}
112 78
113int 79int
114nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence, 80nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan)
115 bool emit)
116{ 81{
117 struct nouveau_fence *fence;
118 int ret = 0;
119
120 fence = kzalloc(sizeof(*fence), GFP_KERNEL);
121 if (!fence)
122 return -ENOMEM;
123 kref_init(&fence->refcount);
124 nouveau_channel_ref(chan, &fence->channel);
125
126 if (emit)
127 ret = nouveau_fence_emit(fence);
128
129 if (ret)
130 nouveau_fence_unref(&fence);
131 *pfence = fence;
132 return ret;
133}
134
135struct nouveau_channel *
136nouveau_fence_channel(struct nouveau_fence *fence)
137{
138 return fence ? nouveau_channel_get_unlocked(fence->channel) : NULL;
139}
140
141int
142nouveau_fence_emit(struct nouveau_fence *fence)
143{
144 struct nouveau_channel *chan = fence->channel;
145 struct drm_device *dev = chan->dev; 82 struct drm_device *dev = chan->dev;
146 struct drm_nouveau_private *dev_priv = dev->dev_private; 83 struct drm_nouveau_private *dev_priv = dev->dev_private;
147 int ret; 84 int ret;
@@ -158,10 +95,11 @@ nouveau_fence_emit(struct nouveau_fence *fence)
158 } 95 }
159 96
160 fence->sequence = ++chan->fence.sequence; 97 fence->sequence = ++chan->fence.sequence;
98 fence->channel = chan;
161 99
162 kref_get(&fence->refcount); 100 kref_get(&fence->kref);
163 spin_lock(&chan->fence.lock); 101 spin_lock(&chan->fence.lock);
164 list_add_tail(&fence->entry, &chan->fence.pending); 102 list_add_tail(&fence->head, &chan->fence.pending);
165 spin_unlock(&chan->fence.lock); 103 spin_unlock(&chan->fence.lock);
166 104
167 if (USE_REFCNT(dev)) { 105 if (USE_REFCNT(dev)) {
@@ -179,50 +117,12 @@ nouveau_fence_emit(struct nouveau_fence *fence)
179 return 0; 117 return 0;
180} 118}
181 119
182void
183nouveau_fence_work(struct nouveau_fence *fence,
184 void (*work)(void *priv, bool signalled),
185 void *priv)
186{
187 BUG_ON(fence->work);
188
189 spin_lock(&fence->channel->fence.lock);
190
191 if (fence->signalled) {
192 work(priv, true);
193 } else {
194 fence->work = work;
195 fence->priv = priv;
196 }
197
198 spin_unlock(&fence->channel->fence.lock);
199}
200
201void
202nouveau_fence_unref(struct nouveau_fence **pfence)
203{
204 if (*pfence)
205 kref_put(&(*pfence)->refcount, nouveau_fence_del);
206 *pfence = NULL;
207}
208
209struct nouveau_fence *
210nouveau_fence_ref(struct nouveau_fence *fence)
211{
212 kref_get(&fence->refcount);
213 return fence;
214}
215
216bool 120bool
217nouveau_fence_signalled(struct nouveau_fence *fence) 121nouveau_fence_done(struct nouveau_fence *fence)
218{ 122{
219 struct nouveau_channel *chan = fence->channel; 123 if (fence->channel)
220 124 nouveau_fence_update(fence->channel);
221 if (fence->signalled) 125 return !fence->channel;
222 return true;
223
224 nouveau_fence_update(chan);
225 return fence->signalled;
226} 126}
227 127
228int 128int
@@ -232,8 +132,8 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr)
232 ktime_t t; 132 ktime_t t;
233 int ret = 0; 133 int ret = 0;
234 134
235 while (!nouveau_fence_signalled(fence)) { 135 while (!nouveau_fence_done(fence)) {
236 if (time_after_eq(jiffies, fence->timeout)) { 136 if (fence->timeout && time_after_eq(jiffies, fence->timeout)) {
237 ret = -EBUSY; 137 ret = -EBUSY;
238 break; 138 break;
239 } 139 }
@@ -255,10 +155,71 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr)
255 } 155 }
256 156
257 __set_current_state(TASK_RUNNING); 157 __set_current_state(TASK_RUNNING);
158 return ret;
159}
160
161static void
162nouveau_fence_del(struct kref *kref)
163{
164 struct nouveau_fence *fence = container_of(kref, typeof(*fence), kref);
165 kfree(fence);
166}
167
168void
169nouveau_fence_unref(struct nouveau_fence **pfence)
170{
171 if (*pfence)
172 kref_put(&(*pfence)->kref, nouveau_fence_del);
173 *pfence = NULL;
174}
175
176struct nouveau_fence *
177nouveau_fence_ref(struct nouveau_fence *fence)
178{
179 kref_get(&fence->kref);
180 return fence;
181}
182
183int
184nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence)
185{
186 struct nouveau_fence *fence;
187 int ret = 0;
258 188
189 fence = kzalloc(sizeof(*fence), GFP_KERNEL);
190 if (!fence)
191 return -ENOMEM;
192 kref_init(&fence->kref);
193
194 if (chan) {
195 ret = nouveau_fence_emit(fence, chan);
196 if (ret)
197 nouveau_fence_unref(&fence);
198 }
199
200 *pfence = fence;
259 return ret; 201 return ret;
260} 202}
261 203
204struct nouveau_semaphore {
205 struct kref ref;
206 struct drm_device *dev;
207 struct drm_mm_node *mem;
208};
209
210void
211nouveau_fence_work(struct nouveau_fence *fence,
212 void (*work)(void *priv, bool signalled),
213 void *priv)
214{
215 if (!fence->channel) {
216 work(priv, true);
217 } else {
218 fence->work = work;
219 fence->priv = priv;
220 }
221}
222
262static struct nouveau_semaphore * 223static struct nouveau_semaphore *
263semaphore_alloc(struct drm_device *dev) 224semaphore_alloc(struct drm_device *dev)
264{ 225{
@@ -367,7 +328,7 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
367 } 328 }
368 329
369 /* Delay semaphore destruction until its work is done */ 330 /* Delay semaphore destruction until its work is done */
370 ret = nouveau_fence_new(chan, &fence, true); 331 ret = nouveau_fence_new(chan, &fence);
371 if (ret) 332 if (ret)
372 return ret; 333 return ret;
373 334
@@ -421,7 +382,7 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
421 } 382 }
422 383
423 /* Delay semaphore destruction until its work is done */ 384 /* Delay semaphore destruction until its work is done */
424 ret = nouveau_fence_new(chan, &fence, true); 385 ret = nouveau_fence_new(chan, &fence);
425 if (ret) 386 if (ret)
426 return ret; 387 return ret;
427 388
@@ -435,13 +396,13 @@ int
435nouveau_fence_sync(struct nouveau_fence *fence, 396nouveau_fence_sync(struct nouveau_fence *fence,
436 struct nouveau_channel *wchan) 397 struct nouveau_channel *wchan)
437{ 398{
438 struct nouveau_channel *chan = nouveau_fence_channel(fence); 399 struct nouveau_channel *chan;
439 struct drm_device *dev = wchan->dev; 400 struct drm_device *dev = wchan->dev;
440 struct nouveau_semaphore *sema; 401 struct nouveau_semaphore *sema;
441 int ret = 0; 402 int ret = 0;
442 403
443 if (likely(!chan || chan == wchan || 404 chan = fence ? nouveau_channel_get_unlocked(fence->channel) : NULL;
444 nouveau_fence_signalled(fence))) 405 if (likely(!chan || chan == wchan || nouveau_fence_done(fence)))
445 goto out; 406 goto out;
446 407
447 sema = semaphore_alloc(dev); 408 sema = semaphore_alloc(dev);
@@ -480,12 +441,6 @@ out:
480} 441}
481 442
482int 443int
483__nouveau_fence_flush(void *sync_obj, void *sync_arg)
484{
485 return 0;
486}
487
488int
489nouveau_fence_channel_init(struct nouveau_channel *chan) 444nouveau_fence_channel_init(struct nouveau_channel *chan)
490{ 445{
491 struct drm_device *dev = chan->dev; 446 struct drm_device *dev = chan->dev;
@@ -538,14 +493,14 @@ nouveau_fence_channel_fini(struct nouveau_channel *chan)
538 struct nouveau_fence *tmp, *fence; 493 struct nouveau_fence *tmp, *fence;
539 494
540 spin_lock(&chan->fence.lock); 495 spin_lock(&chan->fence.lock);
541 list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { 496 list_for_each_entry_safe(fence, tmp, &chan->fence.pending, head) {
542 fence->signalled = true; 497 fence->channel = NULL;
543 list_del(&fence->entry); 498 list_del(&fence->head);
544 499
545 if (unlikely(fence->work)) 500 if (unlikely(fence->work))
546 fence->work(fence->priv, false); 501 fence->work(fence->priv, false);
547 502
548 kref_put(&fence->refcount, nouveau_fence_del); 503 kref_put(&fence->kref, nouveau_fence_del);
549 } 504 }
550 spin_unlock(&chan->fence.lock); 505 spin_unlock(&chan->fence.lock);
551 506