diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2013-02-13 22:43:21 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2013-02-20 01:00:53 -0500 |
commit | 264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30 (patch) | |
tree | 68ba7f61bc07f54378e562ce385f60dc814b4fad /drivers/gpu | |
parent | 827520ce06568f699dad275dcca61647cce08757 (diff) |
drm/nv84-/fence: prepare for emit/sync support of sysram sequences
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bo.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_chan.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_display.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fence.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fence.h | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_gem.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv84_fence.c | 59 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvc0_fence.c | 33 |
8 files changed, 65 insertions, 62 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 69d7b1d0b9d6..fce944c17a55 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
@@ -561,7 +561,7 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, | |||
561 | struct nouveau_fence *fence = NULL; | 561 | struct nouveau_fence *fence = NULL; |
562 | int ret; | 562 | int ret; |
563 | 563 | ||
564 | ret = nouveau_fence_new(chan, &fence); | 564 | ret = nouveau_fence_new(chan, false, &fence); |
565 | if (ret) | 565 | if (ret) |
566 | return ret; | 566 | return ret; |
567 | 567 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 525a5177b622..eaa80a2b81ee 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c | |||
@@ -51,7 +51,7 @@ nouveau_channel_idle(struct nouveau_channel *chan) | |||
51 | struct nouveau_fence *fence = NULL; | 51 | struct nouveau_fence *fence = NULL; |
52 | int ret; | 52 | int ret; |
53 | 53 | ||
54 | ret = nouveau_fence_new(chan, &fence); | 54 | ret = nouveau_fence_new(chan, false, &fence); |
55 | if (!ret) { | 55 | if (!ret) { |
56 | ret = nouveau_fence_wait(fence, false, false); | 56 | ret = nouveau_fence_wait(fence, false, false); |
57 | nouveau_fence_unref(&fence); | 57 | nouveau_fence_unref(&fence); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 78fc5aa5f5dc..de87417a8167 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -540,7 +540,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, | |||
540 | } | 540 | } |
541 | FIRE_RING (chan); | 541 | FIRE_RING (chan); |
542 | 542 | ||
543 | ret = nouveau_fence_new(chan, pfence); | 543 | ret = nouveau_fence_new(chan, false, pfence); |
544 | if (ret) | 544 | if (ret) |
545 | goto fail; | 545 | goto fail; |
546 | 546 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 6a7a5b576273..6c946837a0aa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c | |||
@@ -41,8 +41,6 @@ nouveau_fence_context_del(struct nouveau_fence_chan *fctx) | |||
41 | struct nouveau_fence *fence, *fnext; | 41 | struct nouveau_fence *fence, *fnext; |
42 | spin_lock(&fctx->lock); | 42 | spin_lock(&fctx->lock); |
43 | list_for_each_entry_safe(fence, fnext, &fctx->pending, head) { | 43 | list_for_each_entry_safe(fence, fnext, &fctx->pending, head) { |
44 | if (fence->work) | ||
45 | fence->work(fence->priv, false); | ||
46 | fence->channel = NULL; | 44 | fence->channel = NULL; |
47 | list_del(&fence->head); | 45 | list_del(&fence->head); |
48 | nouveau_fence_unref(&fence); | 46 | nouveau_fence_unref(&fence); |
@@ -69,8 +67,6 @@ nouveau_fence_update(struct nouveau_channel *chan) | |||
69 | if (fctx->read(chan) < fence->sequence) | 67 | if (fctx->read(chan) < fence->sequence) |
70 | break; | 68 | break; |
71 | 69 | ||
72 | if (fence->work) | ||
73 | fence->work(fence->priv, true); | ||
74 | fence->channel = NULL; | 70 | fence->channel = NULL; |
75 | list_del(&fence->head); | 71 | list_del(&fence->head); |
76 | nouveau_fence_unref(&fence); | 72 | nouveau_fence_unref(&fence); |
@@ -256,7 +252,8 @@ nouveau_fence_ref(struct nouveau_fence *fence) | |||
256 | } | 252 | } |
257 | 253 | ||
258 | int | 254 | int |
259 | nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence) | 255 | nouveau_fence_new(struct nouveau_channel *chan, bool sysmem, |
256 | struct nouveau_fence **pfence) | ||
260 | { | 257 | { |
261 | struct nouveau_fence *fence; | 258 | struct nouveau_fence *fence; |
262 | int ret = 0; | 259 | int ret = 0; |
@@ -267,6 +264,8 @@ nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence) | |||
267 | fence = kzalloc(sizeof(*fence), GFP_KERNEL); | 264 | fence = kzalloc(sizeof(*fence), GFP_KERNEL); |
268 | if (!fence) | 265 | if (!fence) |
269 | return -ENOMEM; | 266 | return -ENOMEM; |
267 | |||
268 | fence->sysmem = sysmem; | ||
270 | kref_init(&fence->kref); | 269 | kref_init(&fence->kref); |
271 | 270 | ||
272 | ret = nouveau_fence_emit(fence, chan); | 271 | ret = nouveau_fence_emit(fence, chan); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index a5c47e348e22..c89943407b52 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h | |||
@@ -7,15 +7,15 @@ struct nouveau_fence { | |||
7 | struct list_head head; | 7 | struct list_head head; |
8 | struct kref kref; | 8 | struct kref kref; |
9 | 9 | ||
10 | bool sysmem; | ||
11 | |||
10 | struct nouveau_channel *channel; | 12 | struct nouveau_channel *channel; |
11 | unsigned long timeout; | 13 | unsigned long timeout; |
12 | u32 sequence; | 14 | u32 sequence; |
13 | |||
14 | void (*work)(void *priv, bool signalled); | ||
15 | void *priv; | ||
16 | }; | 15 | }; |
17 | 16 | ||
18 | int nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **); | 17 | int nouveau_fence_new(struct nouveau_channel *, bool sysmem, |
18 | struct nouveau_fence **); | ||
19 | struct nouveau_fence * | 19 | struct nouveau_fence * |
20 | nouveau_fence_ref(struct nouveau_fence *); | 20 | nouveau_fence_ref(struct nouveau_fence *); |
21 | void nouveau_fence_unref(struct nouveau_fence **); | 21 | void nouveau_fence_unref(struct nouveau_fence **); |
@@ -79,24 +79,18 @@ int nouveau_flip_complete(void *chan); | |||
79 | struct nv84_fence_chan { | 79 | struct nv84_fence_chan { |
80 | struct nouveau_fence_chan base; | 80 | struct nouveau_fence_chan base; |
81 | struct nouveau_vma vma; | 81 | struct nouveau_vma vma; |
82 | struct nouveau_vma vma_gart; | ||
82 | struct nouveau_vma dispc_vma[4]; | 83 | struct nouveau_vma dispc_vma[4]; |
83 | }; | 84 | }; |
84 | 85 | ||
85 | struct nv84_fence_priv { | 86 | struct nv84_fence_priv { |
86 | struct nouveau_fence_priv base; | 87 | struct nouveau_fence_priv base; |
87 | struct nouveau_bo *bo; | 88 | struct nouveau_bo *bo; |
89 | struct nouveau_bo *bo_gart; | ||
88 | u32 *suspend; | 90 | u32 *suspend; |
89 | }; | 91 | }; |
90 | 92 | ||
91 | u64 nv84_fence_crtc(struct nouveau_channel *, int); | 93 | u64 nv84_fence_crtc(struct nouveau_channel *, int); |
92 | int nv84_fence_emit(struct nouveau_fence *); | ||
93 | int nv84_fence_sync(struct nouveau_fence *, struct nouveau_channel *, | ||
94 | struct nouveau_channel *); | ||
95 | u32 nv84_fence_read(struct nouveau_channel *); | ||
96 | int nv84_fence_context_new(struct nouveau_channel *); | 94 | int nv84_fence_context_new(struct nouveau_channel *); |
97 | void nv84_fence_context_del(struct nouveau_channel *); | ||
98 | bool nv84_fence_suspend(struct nouveau_drm *); | ||
99 | void nv84_fence_resume(struct nouveau_drm *); | ||
100 | void nv84_fence_destroy(struct nouveau_drm *); | ||
101 | 95 | ||
102 | #endif | 96 | #endif |
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 706113880622..6c45ddb9ebe9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
@@ -787,7 +787,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, | |||
787 | } | 787 | } |
788 | } | 788 | } |
789 | 789 | ||
790 | ret = nouveau_fence_new(chan, &fence); | 790 | ret = nouveau_fence_new(chan, false, &fence); |
791 | if (ret) { | 791 | if (ret) { |
792 | NV_ERROR(cli, "error fencing pushbuf: %d\n", ret); | 792 | NV_ERROR(cli, "error fencing pushbuf: %d\n", ret); |
793 | WIND_RING(chan); | 793 | WIND_RING(chan); |
diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index bc6493c1a1ef..9fd475c89820 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c | |||
@@ -76,27 +76,39 @@ nv84_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence) | |||
76 | return ret; | 76 | return ret; |
77 | } | 77 | } |
78 | 78 | ||
79 | int | 79 | static int |
80 | nv84_fence_emit(struct nouveau_fence *fence) | 80 | nv84_fence_emit(struct nouveau_fence *fence) |
81 | { | 81 | { |
82 | struct nouveau_channel *chan = fence->channel; | 82 | struct nouveau_channel *chan = fence->channel; |
83 | struct nv84_fence_chan *fctx = chan->fence; | 83 | struct nv84_fence_chan *fctx = chan->fence; |
84 | struct nouveau_fifo_chan *fifo = (void *)chan->object; | 84 | struct nouveau_fifo_chan *fifo = (void *)chan->object; |
85 | u64 addr = fctx->vma.offset + fifo->chid * 16; | 85 | u64 addr = fifo->chid * 16; |
86 | |||
87 | if (fence->sysmem) | ||
88 | addr += fctx->vma_gart.offset; | ||
89 | else | ||
90 | addr += fctx->vma.offset; | ||
91 | |||
86 | return fctx->base.emit32(chan, addr, fence->sequence); | 92 | return fctx->base.emit32(chan, addr, fence->sequence); |
87 | } | 93 | } |
88 | 94 | ||
89 | int | 95 | static int |
90 | nv84_fence_sync(struct nouveau_fence *fence, | 96 | nv84_fence_sync(struct nouveau_fence *fence, |
91 | struct nouveau_channel *prev, struct nouveau_channel *chan) | 97 | struct nouveau_channel *prev, struct nouveau_channel *chan) |
92 | { | 98 | { |
93 | struct nv84_fence_chan *fctx = chan->fence; | 99 | struct nv84_fence_chan *fctx = chan->fence; |
94 | struct nouveau_fifo_chan *fifo = (void *)prev->object; | 100 | struct nouveau_fifo_chan *fifo = (void *)prev->object; |
95 | u64 addr = fctx->vma.offset + fifo->chid * 16; | 101 | u64 addr = fifo->chid * 16; |
102 | |||
103 | if (fence->sysmem) | ||
104 | addr += fctx->vma_gart.offset; | ||
105 | else | ||
106 | addr += fctx->vma.offset; | ||
107 | |||
96 | return fctx->base.sync32(chan, addr, fence->sequence); | 108 | return fctx->base.sync32(chan, addr, fence->sequence); |
97 | } | 109 | } |
98 | 110 | ||
99 | u32 | 111 | static u32 |
100 | nv84_fence_read(struct nouveau_channel *chan) | 112 | nv84_fence_read(struct nouveau_channel *chan) |
101 | { | 113 | { |
102 | struct nouveau_fifo_chan *fifo = (void *)chan->object; | 114 | struct nouveau_fifo_chan *fifo = (void *)chan->object; |
@@ -104,7 +116,7 @@ nv84_fence_read(struct nouveau_channel *chan) | |||
104 | return nouveau_bo_rd32(priv->bo, fifo->chid * 16/4); | 116 | return nouveau_bo_rd32(priv->bo, fifo->chid * 16/4); |
105 | } | 117 | } |
106 | 118 | ||
107 | void | 119 | static void |
108 | nv84_fence_context_del(struct nouveau_channel *chan) | 120 | nv84_fence_context_del(struct nouveau_channel *chan) |
109 | { | 121 | { |
110 | struct drm_device *dev = chan->drm->dev; | 122 | struct drm_device *dev = chan->drm->dev; |
@@ -117,6 +129,7 @@ nv84_fence_context_del(struct nouveau_channel *chan) | |||
117 | nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); | 129 | nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); |
118 | } | 130 | } |
119 | 131 | ||
132 | nouveau_bo_vma_del(priv->bo, &fctx->vma_gart); | ||
120 | nouveau_bo_vma_del(priv->bo, &fctx->vma); | 133 | nouveau_bo_vma_del(priv->bo, &fctx->vma); |
121 | nouveau_fence_context_del(&fctx->base); | 134 | nouveau_fence_context_del(&fctx->base); |
122 | chan->fence = NULL; | 135 | chan->fence = NULL; |
@@ -144,8 +157,10 @@ nv84_fence_context_new(struct nouveau_channel *chan) | |||
144 | fctx->base.sync32 = nv84_fence_sync32; | 157 | fctx->base.sync32 = nv84_fence_sync32; |
145 | 158 | ||
146 | ret = nouveau_bo_vma_add(priv->bo, client->vm, &fctx->vma); | 159 | ret = nouveau_bo_vma_add(priv->bo, client->vm, &fctx->vma); |
147 | if (ret) | 160 | if (ret == 0) { |
148 | nv84_fence_context_del(chan); | 161 | ret = nouveau_bo_vma_add(priv->bo_gart, client->vm, |
162 | &fctx->vma_gart); | ||
163 | } | ||
149 | 164 | ||
150 | /* map display semaphore buffers into channel's vm */ | 165 | /* map display semaphore buffers into channel's vm */ |
151 | for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { | 166 | for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { |
@@ -154,10 +169,13 @@ nv84_fence_context_new(struct nouveau_channel *chan) | |||
154 | } | 169 | } |
155 | 170 | ||
156 | nouveau_bo_wr32(priv->bo, fifo->chid * 16/4, 0x00000000); | 171 | nouveau_bo_wr32(priv->bo, fifo->chid * 16/4, 0x00000000); |
172 | |||
173 | if (ret) | ||
174 | nv84_fence_context_del(chan); | ||
157 | return ret; | 175 | return ret; |
158 | } | 176 | } |
159 | 177 | ||
160 | bool | 178 | static bool |
161 | nv84_fence_suspend(struct nouveau_drm *drm) | 179 | nv84_fence_suspend(struct nouveau_drm *drm) |
162 | { | 180 | { |
163 | struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); | 181 | struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); |
@@ -173,7 +191,7 @@ nv84_fence_suspend(struct nouveau_drm *drm) | |||
173 | return priv->suspend != NULL; | 191 | return priv->suspend != NULL; |
174 | } | 192 | } |
175 | 193 | ||
176 | void | 194 | static void |
177 | nv84_fence_resume(struct nouveau_drm *drm) | 195 | nv84_fence_resume(struct nouveau_drm *drm) |
178 | { | 196 | { |
179 | struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); | 197 | struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); |
@@ -188,10 +206,14 @@ nv84_fence_resume(struct nouveau_drm *drm) | |||
188 | } | 206 | } |
189 | } | 207 | } |
190 | 208 | ||
191 | void | 209 | static void |
192 | nv84_fence_destroy(struct nouveau_drm *drm) | 210 | nv84_fence_destroy(struct nouveau_drm *drm) |
193 | { | 211 | { |
194 | struct nv84_fence_priv *priv = drm->fence; | 212 | struct nv84_fence_priv *priv = drm->fence; |
213 | nouveau_bo_unmap(priv->bo_gart); | ||
214 | if (priv->bo_gart) | ||
215 | nouveau_bo_unpin(priv->bo_gart); | ||
216 | nouveau_bo_ref(NULL, &priv->bo_gart); | ||
195 | nouveau_bo_unmap(priv->bo); | 217 | nouveau_bo_unmap(priv->bo); |
196 | if (priv->bo) | 218 | if (priv->bo) |
197 | nouveau_bo_unpin(priv->bo); | 219 | nouveau_bo_unpin(priv->bo); |
@@ -233,6 +255,21 @@ nv84_fence_create(struct nouveau_drm *drm) | |||
233 | nouveau_bo_ref(NULL, &priv->bo); | 255 | nouveau_bo_ref(NULL, &priv->bo); |
234 | } | 256 | } |
235 | 257 | ||
258 | if (ret == 0) | ||
259 | ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0, | ||
260 | TTM_PL_FLAG_TT, 0, 0, NULL, | ||
261 | &priv->bo_gart); | ||
262 | if (ret == 0) { | ||
263 | ret = nouveau_bo_pin(priv->bo_gart, TTM_PL_FLAG_TT); | ||
264 | if (ret == 0) { | ||
265 | ret = nouveau_bo_map(priv->bo_gart); | ||
266 | if (ret) | ||
267 | nouveau_bo_unpin(priv->bo_gart); | ||
268 | } | ||
269 | if (ret) | ||
270 | nouveau_bo_ref(NULL, &priv->bo_gart); | ||
271 | } | ||
272 | |||
236 | if (ret) | 273 | if (ret) |
237 | nv84_fence_destroy(drm); | 274 | nv84_fence_destroy(drm); |
238 | return ret; | 275 | return ret; |
diff --git a/drivers/gpu/drm/nouveau/nvc0_fence.c b/drivers/gpu/drm/nouveau/nvc0_fence.c index b7def390d808..9566267fbc42 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fence.c +++ b/drivers/gpu/drm/nouveau/nvc0_fence.c | |||
@@ -81,37 +81,10 @@ nvc0_fence_context_new(struct nouveau_channel *chan) | |||
81 | int | 81 | int |
82 | nvc0_fence_create(struct nouveau_drm *drm) | 82 | nvc0_fence_create(struct nouveau_drm *drm) |
83 | { | 83 | { |
84 | struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); | 84 | int ret = nv84_fence_create(drm); |
85 | struct nv84_fence_priv *priv; | ||
86 | int ret; | ||
87 | |||
88 | priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
89 | if (!priv) | ||
90 | return -ENOMEM; | ||
91 | |||
92 | priv->base.dtor = nv84_fence_destroy; | ||
93 | priv->base.suspend = nv84_fence_suspend; | ||
94 | priv->base.resume = nv84_fence_resume; | ||
95 | priv->base.context_new = nvc0_fence_context_new; | ||
96 | priv->base.context_del = nv84_fence_context_del; | ||
97 | |||
98 | init_waitqueue_head(&priv->base.waiting); | ||
99 | priv->base.uevent = true; | ||
100 | |||
101 | ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0, | ||
102 | TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo); | ||
103 | if (ret == 0) { | 85 | if (ret == 0) { |
104 | ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); | 86 | struct nv84_fence_priv *priv = drm->fence; |
105 | if (ret == 0) { | 87 | priv->base.context_new = nvc0_fence_context_new; |
106 | ret = nouveau_bo_map(priv->bo); | ||
107 | if (ret) | ||
108 | nouveau_bo_unpin(priv->bo); | ||
109 | } | ||
110 | if (ret) | ||
111 | nouveau_bo_ref(NULL, &priv->bo); | ||
112 | } | 88 | } |
113 | |||
114 | if (ret) | ||
115 | nv84_fence_destroy(drm); | ||
116 | return ret; | 89 | return ret; |
117 | } | 90 | } |