aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvc0_fence.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvc0_fence.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fence.c186
1 files changed, 20 insertions, 166 deletions
diff --git a/drivers/gpu/drm/nouveau/nvc0_fence.c b/drivers/gpu/drm/nouveau/nvc0_fence.c
index 2a56b1b551cb..9566267fbc42 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fence.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fence.c
@@ -34,203 +34,57 @@
34 34
35#include "nv50_display.h" 35#include "nv50_display.h"
36 36
37struct nvc0_fence_priv {
38 struct nouveau_fence_priv base;
39 struct nouveau_bo *bo;
40 u32 *suspend;
41};
42
43struct nvc0_fence_chan {
44 struct nouveau_fence_chan base;
45 struct nouveau_vma vma;
46 struct nouveau_vma dispc_vma[4];
47};
48
49u64
50nvc0_fence_crtc(struct nouveau_channel *chan, int crtc)
51{
52 struct nvc0_fence_chan *fctx = chan->fence;
53 return fctx->dispc_vma[crtc].offset;
54}
55
56static int 37static int
57nvc0_fence_emit(struct nouveau_fence *fence) 38nvc0_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence)
58{ 39{
59 struct nouveau_channel *chan = fence->channel; 40 int ret = RING_SPACE(chan, 6);
60 struct nvc0_fence_chan *fctx = chan->fence;
61 struct nouveau_fifo_chan *fifo = (void *)chan->object;
62 u64 addr = fctx->vma.offset + fifo->chid * 16;
63 int ret;
64
65 ret = RING_SPACE(chan, 5);
66 if (ret == 0) { 41 if (ret == 0) {
67 BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 42 BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 5);
68 OUT_RING (chan, upper_32_bits(addr)); 43 OUT_RING (chan, upper_32_bits(virtual));
69 OUT_RING (chan, lower_32_bits(addr)); 44 OUT_RING (chan, lower_32_bits(virtual));
70 OUT_RING (chan, fence->sequence); 45 OUT_RING (chan, sequence);
71 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG); 46 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG);
47 OUT_RING (chan, 0x00000000);
72 FIRE_RING (chan); 48 FIRE_RING (chan);
73 } 49 }
74
75 return ret; 50 return ret;
76} 51}
77 52
78static int 53static int
79nvc0_fence_sync(struct nouveau_fence *fence, 54nvc0_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence)
80 struct nouveau_channel *prev, struct nouveau_channel *chan)
81{ 55{
82 struct nvc0_fence_chan *fctx = chan->fence; 56 int ret = RING_SPACE(chan, 5);
83 struct nouveau_fifo_chan *fifo = (void *)prev->object;
84 u64 addr = fctx->vma.offset + fifo->chid * 16;
85 int ret;
86
87 ret = RING_SPACE(chan, 5);
88 if (ret == 0) { 57 if (ret == 0) {
89 BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 58 BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
90 OUT_RING (chan, upper_32_bits(addr)); 59 OUT_RING (chan, upper_32_bits(virtual));
91 OUT_RING (chan, lower_32_bits(addr)); 60 OUT_RING (chan, lower_32_bits(virtual));
92 OUT_RING (chan, fence->sequence); 61 OUT_RING (chan, sequence);
93 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL | 62 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL |
94 NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD); 63 NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD);
95 FIRE_RING (chan); 64 FIRE_RING (chan);
96 } 65 }
97
98 return ret; 66 return ret;
99} 67}
100 68
101static u32
102nvc0_fence_read(struct nouveau_channel *chan)
103{
104 struct nouveau_fifo_chan *fifo = (void *)chan->object;
105 struct nvc0_fence_priv *priv = chan->drm->fence;
106 return nouveau_bo_rd32(priv->bo, fifo->chid * 16/4);
107}
108
109static void
110nvc0_fence_context_del(struct nouveau_channel *chan)
111{
112 struct drm_device *dev = chan->drm->dev;
113 struct nvc0_fence_priv *priv = chan->drm->fence;
114 struct nvc0_fence_chan *fctx = chan->fence;
115 int i;
116
117 for (i = 0; i < dev->mode_config.num_crtc; i++) {
118 struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i);
119 nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]);
120 }
121
122 nouveau_bo_vma_del(priv->bo, &fctx->vma);
123 nouveau_fence_context_del(&fctx->base);
124 chan->fence = NULL;
125 kfree(fctx);
126}
127
128static int 69static int
129nvc0_fence_context_new(struct nouveau_channel *chan) 70nvc0_fence_context_new(struct nouveau_channel *chan)
130{ 71{
131 struct nouveau_fifo_chan *fifo = (void *)chan->object; 72 int ret = nv84_fence_context_new(chan);
132 struct nouveau_client *client = nouveau_client(fifo); 73 if (ret == 0) {
133 struct nvc0_fence_priv *priv = chan->drm->fence; 74 struct nv84_fence_chan *fctx = chan->fence;
134 struct nvc0_fence_chan *fctx; 75 fctx->base.emit32 = nvc0_fence_emit32;
135 int ret, i; 76 fctx->base.sync32 = nvc0_fence_sync32;
136
137 fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
138 if (!fctx)
139 return -ENOMEM;
140
141 nouveau_fence_context_new(&fctx->base);
142
143 ret = nouveau_bo_vma_add(priv->bo, client->vm, &fctx->vma);
144 if (ret)
145 nvc0_fence_context_del(chan);
146
147 /* map display semaphore buffers into channel's vm */
148 for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) {
149 struct nouveau_bo *bo = nv50_display_crtc_sema(chan->drm->dev, i);
150 ret = nouveau_bo_vma_add(bo, client->vm, &fctx->dispc_vma[i]);
151 } 77 }
152
153 nouveau_bo_wr32(priv->bo, fifo->chid * 16/4, 0x00000000);
154 return ret; 78 return ret;
155} 79}
156 80
157static bool
158nvc0_fence_suspend(struct nouveau_drm *drm)
159{
160 struct nouveau_fifo *pfifo = nouveau_fifo(drm->device);
161 struct nvc0_fence_priv *priv = drm->fence;
162 int i;
163
164 priv->suspend = vmalloc((pfifo->max + 1) * sizeof(u32));
165 if (priv->suspend) {
166 for (i = 0; i <= pfifo->max; i++)
167 priv->suspend[i] = nouveau_bo_rd32(priv->bo, i);
168 }
169
170 return priv->suspend != NULL;
171}
172
173static void
174nvc0_fence_resume(struct nouveau_drm *drm)
175{
176 struct nouveau_fifo *pfifo = nouveau_fifo(drm->device);
177 struct nvc0_fence_priv *priv = drm->fence;
178 int i;
179
180 if (priv->suspend) {
181 for (i = 0; i <= pfifo->max; i++)
182 nouveau_bo_wr32(priv->bo, i, priv->suspend[i]);
183 vfree(priv->suspend);
184 priv->suspend = NULL;
185 }
186}
187
188static void
189nvc0_fence_destroy(struct nouveau_drm *drm)
190{
191 struct nvc0_fence_priv *priv = drm->fence;
192 nouveau_bo_unmap(priv->bo);
193 if (priv->bo)
194 nouveau_bo_unpin(priv->bo);
195 nouveau_bo_ref(NULL, &priv->bo);
196 drm->fence = NULL;
197 kfree(priv);
198}
199
200int 81int
201nvc0_fence_create(struct nouveau_drm *drm) 82nvc0_fence_create(struct nouveau_drm *drm)
202{ 83{
203 struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); 84 int ret = nv84_fence_create(drm);
204 struct nvc0_fence_priv *priv;
205 int ret;
206
207 priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL);
208 if (!priv)
209 return -ENOMEM;
210
211 priv->base.dtor = nvc0_fence_destroy;
212 priv->base.suspend = nvc0_fence_suspend;
213 priv->base.resume = nvc0_fence_resume;
214 priv->base.context_new = nvc0_fence_context_new;
215 priv->base.context_del = nvc0_fence_context_del;
216 priv->base.emit = nvc0_fence_emit;
217 priv->base.sync = nvc0_fence_sync;
218 priv->base.read = nvc0_fence_read;
219
220 ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0,
221 TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo);
222 if (ret == 0) { 85 if (ret == 0) {
223 ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); 86 struct nv84_fence_priv *priv = drm->fence;
224 if (ret == 0) { 87 priv->base.context_new = nvc0_fence_context_new;
225 ret = nouveau_bo_map(priv->bo);
226 if (ret)
227 nouveau_bo_unpin(priv->bo);
228 }
229 if (ret)
230 nouveau_bo_ref(NULL, &priv->bo);
231 } 88 }
232
233 if (ret)
234 nvc0_fence_destroy(drm);
235 return ret; 89 return ret;
236} 90}