diff options
author | Francisco Jerez <currojerez@riseup.net> | 2010-09-21 14:49:39 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-10-04 19:59:12 -0400 |
commit | 8ac3891b48906b38db4b153c2d0d55db2ef81aee (patch) | |
tree | a01cfeb53235f2d112e2f327e52d603b7ef67f11 /drivers/gpu/drm/nouveau/nouveau_fence.c | |
parent | 2730723bbc4a8b289fa536fc3555e15947da09c1 (diff) |
drm/nouveau: Provide a means to have arbitrary work run on fence completion.
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
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 | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 62f13189698a..fbb2c3b26239 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c | |||
@@ -39,6 +39,9 @@ struct nouveau_fence { | |||
39 | 39 | ||
40 | uint32_t sequence; | 40 | uint32_t sequence; |
41 | bool signalled; | 41 | bool signalled; |
42 | |||
43 | void (*work)(void *priv, bool signalled); | ||
44 | void *priv; | ||
42 | }; | 45 | }; |
43 | 46 | ||
44 | static inline struct nouveau_fence * | 47 | static inline struct nouveau_fence * |
@@ -78,6 +81,10 @@ nouveau_fence_update(struct nouveau_channel *chan) | |||
78 | sequence = fence->sequence; | 81 | sequence = fence->sequence; |
79 | fence->signalled = true; | 82 | fence->signalled = true; |
80 | list_del(&fence->entry); | 83 | list_del(&fence->entry); |
84 | |||
85 | if (unlikely(fence->work)) | ||
86 | fence->work(fence->priv, true); | ||
87 | |||
81 | kref_put(&fence->refcount, nouveau_fence_del); | 88 | kref_put(&fence->refcount, nouveau_fence_del); |
82 | 89 | ||
83 | if (sequence == chan->fence.sequence_ack) | 90 | if (sequence == chan->fence.sequence_ack) |
@@ -148,6 +155,25 @@ nouveau_fence_emit(struct nouveau_fence *fence) | |||
148 | } | 155 | } |
149 | 156 | ||
150 | void | 157 | void |
158 | nouveau_fence_work(struct nouveau_fence *fence, | ||
159 | void (*work)(void *priv, bool signalled), | ||
160 | void *priv) | ||
161 | { | ||
162 | BUG_ON(fence->work); | ||
163 | |||
164 | spin_lock(&fence->channel->fence.lock); | ||
165 | |||
166 | if (fence->signalled) { | ||
167 | work(priv, true); | ||
168 | } else { | ||
169 | fence->work = work; | ||
170 | fence->priv = priv; | ||
171 | } | ||
172 | |||
173 | spin_unlock(&fence->channel->fence.lock); | ||
174 | } | ||
175 | |||
176 | void | ||
151 | nouveau_fence_unref(void **sync_obj) | 177 | nouveau_fence_unref(void **sync_obj) |
152 | { | 178 | { |
153 | struct nouveau_fence *fence = nouveau_fence(*sync_obj); | 179 | struct nouveau_fence *fence = nouveau_fence(*sync_obj); |
@@ -268,6 +294,10 @@ nouveau_fence_channel_fini(struct nouveau_channel *chan) | |||
268 | list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { | 294 | list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { |
269 | fence->signalled = true; | 295 | fence->signalled = true; |
270 | list_del(&fence->entry); | 296 | list_del(&fence->entry); |
297 | |||
298 | if (unlikely(fence->work)) | ||
299 | fence->work(fence->priv, false); | ||
300 | |||
271 | kref_put(&fence->refcount, nouveau_fence_del); | 301 | kref_put(&fence->refcount, nouveau_fence_del); |
272 | } | 302 | } |
273 | } | 303 | } |