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 | |
parent | 875ac34aad49bb875833aed2b4f2deb7a28df9f0 (diff) |
drm/nouveau/fence: minor api changes for an upcoming rework
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bo.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_channel.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_display.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 26 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fence.c | 215 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fence.h | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_gem.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_mem.c | 3 |
8 files changed, 134 insertions, 158 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 1aa03a83bae0..6d66314d16bd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "nouveau_dma.h" | 35 | #include "nouveau_dma.h" |
36 | #include "nouveau_mm.h" | 36 | #include "nouveau_mm.h" |
37 | #include "nouveau_vm.h" | 37 | #include "nouveau_vm.h" |
38 | #include "nouveau_fence.h" | ||
38 | 39 | ||
39 | #include <linux/log2.h> | 40 | #include <linux/log2.h> |
40 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
@@ -478,7 +479,7 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, | |||
478 | struct nouveau_fence *fence = NULL; | 479 | struct nouveau_fence *fence = NULL; |
479 | int ret; | 480 | int ret; |
480 | 481 | ||
481 | ret = nouveau_fence_new(chan, &fence, true); | 482 | ret = nouveau_fence_new(chan, &fence); |
482 | if (ret) | 483 | if (ret) |
483 | return ret; | 484 | return ret; |
484 | 485 | ||
@@ -1196,7 +1197,7 @@ nouveau_bo_fence_ref(void *sync_obj) | |||
1196 | static bool | 1197 | static bool |
1197 | nouveau_bo_fence_signalled(void *sync_obj, void *sync_arg) | 1198 | nouveau_bo_fence_signalled(void *sync_obj, void *sync_arg) |
1198 | { | 1199 | { |
1199 | return nouveau_fence_signalled(sync_obj); | 1200 | return nouveau_fence_done(sync_obj); |
1200 | } | 1201 | } |
1201 | 1202 | ||
1202 | static int | 1203 | static int |
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 26c08e9b4a33..694f6325311a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "nouveau_drm.h" | 28 | #include "nouveau_drm.h" |
29 | #include "nouveau_dma.h" | 29 | #include "nouveau_dma.h" |
30 | #include "nouveau_ramht.h" | 30 | #include "nouveau_ramht.h" |
31 | #include "nouveau_fence.h" | ||
31 | #include "nouveau_software.h" | 32 | #include "nouveau_software.h" |
32 | 33 | ||
33 | static int | 34 | static int |
@@ -369,7 +370,7 @@ nouveau_channel_idle(struct nouveau_channel *chan) | |||
369 | nouveau_fence_update(chan); | 370 | nouveau_fence_update(chan); |
370 | 371 | ||
371 | if (chan->fence.sequence != chan->fence.sequence_ack) { | 372 | if (chan->fence.sequence != chan->fence.sequence_ack) { |
372 | ret = nouveau_fence_new(chan, &fence, true); | 373 | ret = nouveau_fence_new(chan, &fence); |
373 | if (!ret) { | 374 | if (!ret) { |
374 | ret = nouveau_fence_wait(fence, false, false); | 375 | ret = nouveau_fence_wait(fence, false, false); |
375 | nouveau_fence_unref(&fence); | 376 | nouveau_fence_unref(&fence); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index a13f2516d52f..f9cdc921ef96 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "nouveau_connector.h" | 35 | #include "nouveau_connector.h" |
36 | #include "nouveau_software.h" | 36 | #include "nouveau_software.h" |
37 | #include "nouveau_gpio.h" | 37 | #include "nouveau_gpio.h" |
38 | #include "nouveau_fence.h" | ||
38 | #include "nv50_display.h" | 39 | #include "nv50_display.h" |
39 | 40 | ||
40 | static void | 41 | static void |
@@ -465,7 +466,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, | |||
465 | } | 466 | } |
466 | FIRE_RING (chan); | 467 | FIRE_RING (chan); |
467 | 468 | ||
468 | ret = nouveau_fence_new(chan, pfence, true); | 469 | ret = nouveau_fence_new(chan, pfence); |
469 | if (ret) | 470 | if (ret) |
470 | goto fail; | 471 | goto fail; |
471 | 472 | ||
@@ -486,7 +487,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
486 | struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo; | 487 | struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo; |
487 | struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo; | 488 | struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo; |
488 | struct nouveau_page_flip_state *s; | 489 | struct nouveau_page_flip_state *s; |
489 | struct nouveau_channel *chan; | 490 | struct nouveau_channel *chan = NULL; |
490 | struct nouveau_fence *fence; | 491 | struct nouveau_fence *fence; |
491 | int ret; | 492 | int ret; |
492 | 493 | ||
@@ -509,7 +510,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
509 | new_bo->bo.offset }; | 510 | new_bo->bo.offset }; |
510 | 511 | ||
511 | /* Choose the channel the flip will be handled in */ | 512 | /* Choose the channel the flip will be handled in */ |
512 | chan = nouveau_fence_channel(new_bo->bo.sync_obj); | 513 | fence = new_bo->bo.sync_obj; |
514 | if (fence) | ||
515 | chan = nouveau_channel_get_unlocked(fence->channel); | ||
513 | if (!chan) | 516 | if (!chan) |
514 | chan = nouveau_channel_get_unlocked(dev_priv->channel); | 517 | chan = nouveau_channel_get_unlocked(dev_priv->channel); |
515 | mutex_lock(&chan->mutex); | 518 | mutex_lock(&chan->mutex); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index b17444ae05c8..43a46f157def 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -1444,26 +1444,12 @@ extern int nouveau_bo_vma_add(struct nouveau_bo *, struct nouveau_vm *, | |||
1444 | extern void nouveau_bo_vma_del(struct nouveau_bo *, struct nouveau_vma *); | 1444 | extern void nouveau_bo_vma_del(struct nouveau_bo *, struct nouveau_vma *); |
1445 | 1445 | ||
1446 | /* nouveau_fence.c */ | 1446 | /* nouveau_fence.c */ |
1447 | struct nouveau_fence; | 1447 | int nouveau_fence_init(struct drm_device *); |
1448 | extern int nouveau_fence_init(struct drm_device *); | 1448 | void nouveau_fence_fini(struct drm_device *); |
1449 | extern void nouveau_fence_fini(struct drm_device *); | 1449 | int nouveau_fence_channel_init(struct nouveau_channel *); |
1450 | extern int nouveau_fence_channel_init(struct nouveau_channel *); | 1450 | void nouveau_fence_channel_fini(struct nouveau_channel *); |
1451 | extern void nouveau_fence_channel_fini(struct nouveau_channel *); | 1451 | void nouveau_fence_work(struct nouveau_fence *fence, |
1452 | extern void nouveau_fence_update(struct nouveau_channel *); | 1452 | void (*work)(void *priv, bool signalled), void *priv); |
1453 | extern int nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **, | ||
1454 | bool emit); | ||
1455 | extern int nouveau_fence_emit(struct nouveau_fence *); | ||
1456 | extern void nouveau_fence_work(struct nouveau_fence *fence, | ||
1457 | void (*work)(void *priv, bool signalled), | ||
1458 | void *priv); | ||
1459 | struct nouveau_channel *nouveau_fence_channel(struct nouveau_fence *); | ||
1460 | |||
1461 | extern bool nouveau_fence_signalled(struct nouveau_fence *); | ||
1462 | extern int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); | ||
1463 | extern void nouveau_fence_unref(struct nouveau_fence **); | ||
1464 | extern struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *); | ||
1465 | extern int nouveau_fence_sync(struct nouveau_fence *, struct nouveau_channel *); | ||
1466 | |||
1467 | /* nouveau_gem.c */ | 1453 | /* nouveau_gem.c */ |
1468 | extern int nouveau_gem_new(struct drm_device *, int size, int align, | 1454 | extern int nouveau_gem_new(struct drm_device *, int size, int align, |
1469 | uint32_t domain, uint32_t tile_mode, | 1455 | uint32_t domain, uint32_t tile_mode, |
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 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h new file mode 100644 index 000000000000..1337acb00172 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h | |||
@@ -0,0 +1,28 @@ | |||
1 | #ifndef __NOUVEAU_FENCE_H__ | ||
2 | #define __NOUVEAU_FENCE_H__ | ||
3 | |||
4 | struct nouveau_fence { | ||
5 | struct list_head head; | ||
6 | struct kref kref; | ||
7 | |||
8 | struct nouveau_channel *channel; | ||
9 | unsigned long timeout; | ||
10 | u32 sequence; | ||
11 | |||
12 | void (*work)(void *priv, bool signalled); | ||
13 | void *priv; | ||
14 | }; | ||
15 | |||
16 | int nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **); | ||
17 | struct nouveau_fence * | ||
18 | nouveau_fence_ref(struct nouveau_fence *); | ||
19 | void nouveau_fence_unref(struct nouveau_fence **); | ||
20 | |||
21 | int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *); | ||
22 | bool nouveau_fence_done(struct nouveau_fence *); | ||
23 | int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); | ||
24 | int nouveau_fence_sync(struct nouveau_fence *, struct nouveau_channel *); | ||
25 | void nouveau_fence_idle(struct nouveau_channel *); | ||
26 | void nouveau_fence_update(struct nouveau_channel *); | ||
27 | |||
28 | #endif | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 666dad0717a9..996755a8c9a1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "nouveau_drv.h" | 30 | #include "nouveau_drv.h" |
31 | #include "nouveau_drm.h" | 31 | #include "nouveau_drm.h" |
32 | #include "nouveau_dma.h" | 32 | #include "nouveau_dma.h" |
33 | #include "nouveau_fence.h" | ||
33 | 34 | ||
34 | #define nouveau_gem_pushbuf_sync(chan) 0 | 35 | #define nouveau_gem_pushbuf_sync(chan) 0 |
35 | 36 | ||
@@ -778,7 +779,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, | |||
778 | } | 779 | } |
779 | } | 780 | } |
780 | 781 | ||
781 | ret = nouveau_fence_new(chan, &fence, true); | 782 | ret = nouveau_fence_new(chan, &fence); |
782 | if (ret) { | 783 | if (ret) { |
783 | NV_ERROR(dev, "error fencing pushbuf: %d\n", ret); | 784 | NV_ERROR(dev, "error fencing pushbuf: %d\n", ret); |
784 | WIND_RING(chan); | 785 | WIND_RING(chan); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 585dcbeafcda..193521251773 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include "nouveau_pm.h" | 39 | #include "nouveau_pm.h" |
40 | #include "nouveau_mm.h" | 40 | #include "nouveau_mm.h" |
41 | #include "nouveau_vm.h" | 41 | #include "nouveau_vm.h" |
42 | #include "nouveau_fence.h" | ||
42 | 43 | ||
43 | /* | 44 | /* |
44 | * NV10-NV40 tiling helpers | 45 | * NV10-NV40 tiling helpers |
@@ -89,7 +90,7 @@ nv10_mem_get_tile_region(struct drm_device *dev, int i) | |||
89 | spin_lock(&dev_priv->tile.lock); | 90 | spin_lock(&dev_priv->tile.lock); |
90 | 91 | ||
91 | if (!tile->used && | 92 | if (!tile->used && |
92 | (!tile->fence || nouveau_fence_signalled(tile->fence))) | 93 | (!tile->fence || nouveau_fence_done(tile->fence))) |
93 | tile->used = true; | 94 | tile->used = true; |
94 | else | 95 | else |
95 | tile = NULL; | 96 | tile = NULL; |