aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_fence.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2013-05-06 19:48:30 -0400
committerBen Skeggs <bskeggs@redhat.com>2013-06-30 23:50:31 -0400
commitc4c7044ffc1ba973e2ec0f0dc94980b49101d877 (patch)
tree936ddc8e8ae3b940079e5577a4ad947a90d58343 /drivers/gpu/drm/nouveau/nouveau_fence.c
parent780194b1b9f5fdbaa06dd71e60b31ceaaedafbe4 (diff)
drm/nouveau: delay busy bo vma removal until fence signals
As opposed to an explicit wait. Allows userspace to not stall waiting on buffer deletion. 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.c73
1 files changed, 68 insertions, 5 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index 6c946837a0aa..1680d9187bab 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -35,15 +35,34 @@
35 35
36#include <engine/fifo.h> 36#include <engine/fifo.h>
37 37
38struct fence_work {
39 struct work_struct base;
40 struct list_head head;
41 void (*func)(void *);
42 void *data;
43};
44
45static void
46nouveau_fence_signal(struct nouveau_fence *fence)
47{
48 struct fence_work *work, *temp;
49
50 list_for_each_entry_safe(work, temp, &fence->work, head) {
51 schedule_work(&work->base);
52 list_del(&work->head);
53 }
54
55 fence->channel = NULL;
56 list_del(&fence->head);
57}
58
38void 59void
39nouveau_fence_context_del(struct nouveau_fence_chan *fctx) 60nouveau_fence_context_del(struct nouveau_fence_chan *fctx)
40{ 61{
41 struct nouveau_fence *fence, *fnext; 62 struct nouveau_fence *fence, *fnext;
42 spin_lock(&fctx->lock); 63 spin_lock(&fctx->lock);
43 list_for_each_entry_safe(fence, fnext, &fctx->pending, head) { 64 list_for_each_entry_safe(fence, fnext, &fctx->pending, head) {
44 fence->channel = NULL; 65 nouveau_fence_signal(fence);
45 list_del(&fence->head);
46 nouveau_fence_unref(&fence);
47 } 66 }
48 spin_unlock(&fctx->lock); 67 spin_unlock(&fctx->lock);
49} 68}
@@ -57,6 +76,50 @@ nouveau_fence_context_new(struct nouveau_fence_chan *fctx)
57} 76}
58 77
59static void 78static void
79nouveau_fence_work_handler(struct work_struct *kwork)
80{
81 struct fence_work *work = container_of(kwork, typeof(*work), base);
82 work->func(work->data);
83 kfree(work);
84}
85
86void
87nouveau_fence_work(struct nouveau_fence *fence,
88 void (*func)(void *), void *data)
89{
90 struct nouveau_channel *chan = fence->channel;
91 struct nouveau_fence_chan *fctx;
92 struct fence_work *work = NULL;
93
94 if (nouveau_fence_done(fence)) {
95 func(data);
96 return;
97 }
98
99 fctx = chan->fence;
100 work = kmalloc(sizeof(*work), GFP_KERNEL);
101 if (!work) {
102 WARN_ON(nouveau_fence_wait(fence, false, false));
103 func(data);
104 return;
105 }
106
107 spin_lock(&fctx->lock);
108 if (!fence->channel) {
109 spin_unlock(&fctx->lock);
110 kfree(work);
111 func(data);
112 return;
113 }
114
115 INIT_WORK(&work->base, nouveau_fence_work_handler);
116 work->func = func;
117 work->data = data;
118 list_add(&work->head, &fence->work);
119 spin_unlock(&fctx->lock);
120}
121
122static void
60nouveau_fence_update(struct nouveau_channel *chan) 123nouveau_fence_update(struct nouveau_channel *chan)
61{ 124{
62 struct nouveau_fence_chan *fctx = chan->fence; 125 struct nouveau_fence_chan *fctx = chan->fence;
@@ -67,8 +130,7 @@ nouveau_fence_update(struct nouveau_channel *chan)
67 if (fctx->read(chan) < fence->sequence) 130 if (fctx->read(chan) < fence->sequence)
68 break; 131 break;
69 132
70 fence->channel = NULL; 133 nouveau_fence_signal(fence);
71 list_del(&fence->head);
72 nouveau_fence_unref(&fence); 134 nouveau_fence_unref(&fence);
73 } 135 }
74 spin_unlock(&fctx->lock); 136 spin_unlock(&fctx->lock);
@@ -265,6 +327,7 @@ nouveau_fence_new(struct nouveau_channel *chan, bool sysmem,
265 if (!fence) 327 if (!fence)
266 return -ENOMEM; 328 return -ENOMEM;
267 329
330 INIT_LIST_HEAD(&fence->work);
268 fence->sysmem = sysmem; 331 fence->sysmem = sysmem;
269 kref_init(&fence->kref); 332 kref_init(&fence->kref);
270 333