diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2012-04-29 23:30:00 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2012-05-24 02:55:46 -0400 |
commit | d375e7d56dffa564a6c337d2ed3217fb94826100 (patch) | |
tree | ddce2af34f6c0eee35cb3b5c99cd1707d6b63ae4 /drivers/gpu/drm/nouveau/nouveau_fence.c | |
parent | 875ac34aad49bb875833aed2b4f2deb7a28df9f0 (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.c | 215 |
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 | ||
41 | struct 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 | |||
54 | struct nouveau_semaphore { | ||
55 | struct kref ref; | ||
56 | struct drm_device *dev; | ||
57 | struct drm_mm_node *mem; | ||
58 | }; | ||
59 | |||
60 | static inline struct nouveau_fence * | ||
61 | nouveau_fence(void *sync_obj) | ||
62 | { | ||
63 | return (struct nouveau_fence *)sync_obj; | ||
64 | } | ||
65 | |||
66 | static void | ||
67 | nouveau_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 | |||
76 | void | 42 | void |
77 | nouveau_fence_update(struct nouveau_channel *chan) | 43 | nouveau_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 | ||
109 | out: | 75 | out: |
@@ -111,37 +77,8 @@ out: | |||
111 | } | 77 | } |
112 | 78 | ||
113 | int | 79 | int |
114 | nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence, | 80 | nouveau_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 | |||
135 | struct nouveau_channel * | ||
136 | nouveau_fence_channel(struct nouveau_fence *fence) | ||
137 | { | ||
138 | return fence ? nouveau_channel_get_unlocked(fence->channel) : NULL; | ||
139 | } | ||
140 | |||
141 | int | ||
142 | nouveau_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 | ||
182 | void | ||
183 | nouveau_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 | |||
201 | void | ||
202 | nouveau_fence_unref(struct nouveau_fence **pfence) | ||
203 | { | ||
204 | if (*pfence) | ||
205 | kref_put(&(*pfence)->refcount, nouveau_fence_del); | ||
206 | *pfence = NULL; | ||
207 | } | ||
208 | |||
209 | struct nouveau_fence * | ||
210 | nouveau_fence_ref(struct nouveau_fence *fence) | ||
211 | { | ||
212 | kref_get(&fence->refcount); | ||
213 | return fence; | ||
214 | } | ||
215 | |||
216 | bool | 120 | bool |
217 | nouveau_fence_signalled(struct nouveau_fence *fence) | 121 | nouveau_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 | ||
228 | int | 128 | int |
@@ -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 | |||
161 | static void | ||
162 | nouveau_fence_del(struct kref *kref) | ||
163 | { | ||
164 | struct nouveau_fence *fence = container_of(kref, typeof(*fence), kref); | ||
165 | kfree(fence); | ||
166 | } | ||
167 | |||
168 | void | ||
169 | nouveau_fence_unref(struct nouveau_fence **pfence) | ||
170 | { | ||
171 | if (*pfence) | ||
172 | kref_put(&(*pfence)->kref, nouveau_fence_del); | ||
173 | *pfence = NULL; | ||
174 | } | ||
175 | |||
176 | struct nouveau_fence * | ||
177 | nouveau_fence_ref(struct nouveau_fence *fence) | ||
178 | { | ||
179 | kref_get(&fence->kref); | ||
180 | return fence; | ||
181 | } | ||
182 | |||
183 | int | ||
184 | nouveau_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 | ||
204 | struct nouveau_semaphore { | ||
205 | struct kref ref; | ||
206 | struct drm_device *dev; | ||
207 | struct drm_mm_node *mem; | ||
208 | }; | ||
209 | |||
210 | void | ||
211 | nouveau_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 | |||
262 | static struct nouveau_semaphore * | 223 | static struct nouveau_semaphore * |
263 | semaphore_alloc(struct drm_device *dev) | 224 | semaphore_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 | |||
435 | nouveau_fence_sync(struct nouveau_fence *fence, | 396 | nouveau_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 | ||
482 | int | 443 | int |
483 | __nouveau_fence_flush(void *sync_obj, void *sync_arg) | ||
484 | { | ||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | int | ||
489 | nouveau_fence_channel_init(struct nouveau_channel *chan) | 444 | nouveau_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 | ||