1 /*
2 // Copyright (c) 2014 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 #include <wsbm_pool.h>
18 #include <wsbm_driver.h>
19 #include <wsbm_manager.h>
20 #include <wsbm_util.h>
21 #include <drm/ttm/ttm_placement.h>
22 #include <linux/psb_drm.h>
23 #include <xf86drm.h>
24 #include <HwcTrace.h>
25
26 struct _WsbmBufferPool * mainPool = NULL;
27
28 struct PsbWsbmValidateNode
29 {
30 struct _ValidateNode base;
31 struct psb_validate_arg arg;
32 };
33
align_to(uint32_t arg,uint32_t align)34 static inline uint32_t align_to(uint32_t arg, uint32_t align)
35 {
36 return ((arg + (align - 1)) & (~(align - 1)));
37 }
38
pvrAlloc(struct _WsbmVNodeFuncs * func,int typeId)39 static struct _ValidateNode * pvrAlloc(struct _WsbmVNodeFuncs * func,
40 int typeId)
41 {
42 CTRACE();
43 if(typeId == 0) {
44 struct PsbWsbmValidateNode * vNode = malloc(sizeof(*vNode));
45 if(!vNode) {
46 ETRACE("failed to allocate memory");
47 return NULL;
48 }
49
50 vNode->base.func = func;
51 vNode->base.type_id = 0;
52 return &vNode->base;
53 } else {
54 struct _ValidateNode * node = malloc(sizeof(*node));
55 if(!node) {
56 ETRACE("failed to allocate node");
57 return NULL;
58 }
59
60 node->func = func;
61 node->type_id = 1;
62 return node;
63 }
64 }
65
pvrFree(struct _ValidateNode * node)66 static void pvrFree(struct _ValidateNode * node)
67 {
68 CTRACE();
69 if(node->type_id == 0) {
70 free(containerOf(node, struct PsbWsbmValidateNode, base));
71 } else {
72 free(node);
73 }
74 }
75
pvrClear(struct _ValidateNode * node)76 static void pvrClear(struct _ValidateNode * node)
77 {
78 CTRACE();
79 if(node->type_id == 0) {
80 struct PsbWsbmValidateNode * vNode =
81 containerOf(node, struct PsbWsbmValidateNode, base);
82 memset(&vNode->arg.d.req, 0, sizeof(vNode->arg.d.req));
83 }
84 }
85
86 static struct _WsbmVNodeFuncs vNodeFuncs = {
87 .alloc = pvrAlloc,
88 .free = pvrFree,
89 .clear = pvrClear,
90 };
91
psbWsbmTakedown()92 void psbWsbmTakedown()
93 {
94 CTRACE();
95
96 if (mainPool) {
97 wsbmPoolTakeDown(mainPool);
98 mainPool = NULL;
99 }
100
101 if (wsbmIsInitialized()) {
102 wsbmTakedown();
103 }
104 }
105
psbWsbmInitialize(int drmFD)106 int psbWsbmInitialize(int drmFD)
107 {
108 union drm_psb_extension_arg arg;
109 const char drmExt[] = "psb_ttm_placement_alphadrop";
110 int ret = 0;
111
112 CTRACE();
113
114 if (drmFD <= 0) {
115 ETRACE("invalid drm fd %d", drmFD);
116 return drmFD;
117 }
118
119 /*init wsbm*/
120 ret = wsbmInit(wsbmNullThreadFuncs(), &vNodeFuncs);
121 if (ret) {
122 ETRACE("failed to initialize Wsbm, error code %d", ret);
123 return ret;
124 }
125
126 VTRACE("DRM_PSB_EXTENSION %d", DRM_PSB_EXTENSION);
127
128 /*get devOffset via drm IOCTL*/
129 strncpy(arg.extension, drmExt, sizeof(drmExt));
130
131 ret = drmCommandWriteRead(drmFD, 6/*DRM_PSB_EXTENSION*/, &arg, sizeof(arg));
132 if(ret || !arg.rep.exists) {
133 ETRACE("failed to get device offset, error code %d", ret);
134 goto out;
135 }
136
137 VTRACE("ioctl offset %#x", arg.rep.driver_ioctl_offset);
138
139 mainPool = wsbmTTMPoolInit(drmFD, arg.rep.driver_ioctl_offset);
140 if(!mainPool) {
141 ETRACE("failed to initialize TTM Pool");
142 ret = -EINVAL;
143 goto out;
144 }
145
146 VTRACE("Wsbm initialization succeeded. mainPool %p", mainPool);
147
148 return 0;
149
150 out:
151 psbWsbmTakedown();
152 return ret;
153 }
154
psbWsbmAllocateFromUB(uint32_t size,uint32_t align,void ** buf,void * user_pt)155 int psbWsbmAllocateFromUB(uint32_t size, uint32_t align, void ** buf, void *user_pt)
156 {
157 struct _WsbmBufferObject * wsbmBuf = NULL;
158 int ret = 0;
159 int offset = 0;
160
161 ATRACE("size %d", align_to(size, 4096));
162
163 if(!buf || !user_pt) {
164 ETRACE("invalid parameter");
165 return -EINVAL;
166 }
167
168 VTRACE("mainPool %p", mainPool);
169
170 ret = wsbmGenBuffers(mainPool, 1, &wsbmBuf, align,
171 DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_CACHED |
172 WSBM_PL_FLAG_NO_EVICT | WSBM_PL_FLAG_SHARED);
173 if(ret) {
174 ETRACE("wsbmGenBuffers failed with error code %d", ret);
175 return ret;
176 }
177
178 ret = wsbmBODataUB(wsbmBuf,
179 align_to(size, 4096), NULL, NULL, 0,
180 user_pt);
181
182 if(ret) {
183 ETRACE("wsbmBOData failed with error code %d", ret);
184 /*FIXME: should I unreference this buffer here?*/
185 return ret;
186 }
187
188 *buf = wsbmBuf;
189
190 VTRACE("ttm UB buffer allocated. %p", *buf);
191 return 0;
192 }
193
psbWsbmAllocateTTMBuffer(uint32_t size,uint32_t align,void ** buf)194 int psbWsbmAllocateTTMBuffer(uint32_t size, uint32_t align, void ** buf)
195 {
196 struct _WsbmBufferObject * wsbmBuf = NULL;
197 int ret = 0;
198 int offset = 0;
199
200 ATRACE("size %d", align_to(size, 4096));
201
202 if(!buf) {
203 ETRACE("invalid parameter");
204 return -EINVAL;
205 }
206
207 VTRACE("mainPool %p", mainPool);
208
209 ret = wsbmGenBuffers(mainPool, 1, &wsbmBuf, align,
210 (WSBM_PL_FLAG_VRAM | WSBM_PL_FLAG_TT |
211 WSBM_PL_FLAG_SHARED | WSBM_PL_FLAG_NO_EVICT));
212 if(ret) {
213 ETRACE("wsbmGenBuffers failed with error code %d", ret);
214 return ret;
215 }
216
217 ret = wsbmBOData(wsbmBuf, align_to(size, 4096), NULL, NULL, 0);
218 if(ret) {
219 ETRACE("wsbmBOData failed with error code %d", ret);
220 /*FIXME: should I unreference this buffer here?*/
221 return ret;
222 }
223
224 /* wsbmBOReference(wsbmBuf); */ /* no need to add reference */
225
226 *buf = wsbmBuf;
227
228 VTRACE("ttm buffer allocated. %p", *buf);
229 return 0;
230 }
231
psbWsbmWrapTTMBuffer(uint64_t handle,void ** buf)232 int psbWsbmWrapTTMBuffer(uint64_t handle, void **buf)
233 {
234 int ret = 0;
235 struct _WsbmBufferObject *wsbmBuf;
236
237 if (!buf) {
238 ETRACE("invalid parameter");
239 return -EINVAL;
240 }
241
242 ret = wsbmGenBuffers(mainPool, 1, &wsbmBuf, 0,
243 (WSBM_PL_FLAG_VRAM | WSBM_PL_FLAG_TT |
244 /*WSBM_PL_FLAG_NO_EVICT |*/ WSBM_PL_FLAG_SHARED));
245
246 if (ret) {
247 ETRACE("wsbmGenBuffers failed with error code %d", ret);
248 return ret;
249 }
250
251 ret = wsbmBOSetReferenced(wsbmBuf, handle);
252 if (ret) {
253 ETRACE("wsbmBOSetReferenced failed with error code %d", ret);
254 return ret;
255 }
256
257 *buf = (void *)wsbmBuf;
258
259 VTRACE("wrap buffer %p for handle %#x", wsbmBuf, handle);
260 return 0;
261 }
262
psbWsbmWrapTTMBuffer2(uint64_t handle,void ** buf)263 int psbWsbmWrapTTMBuffer2(uint64_t handle, void **buf)
264 {
265 int ret = 0;
266 struct _WsbmBufferObject *wsbmBuf;
267
268 if (!buf) {
269 ETRACE("invalid parameter");
270 return -EINVAL;
271 }
272
273 ret = wsbmGenBuffers(mainPool, 1, &wsbmBuf, 4096,
274 (WSBM_PL_FLAG_SHARED | DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_UNCACHED));
275
276 if (ret) {
277 ETRACE("wsbmGenBuffers failed with error code %d", ret);
278 return ret;
279 }
280
281 *buf = (void *)wsbmBuf;
282
283 VTRACE("wrap buffer %p for handle %#x", wsbmBuf, handle);
284 return 0;
285 }
286
287
psbWsbmCreateFromUB(void * buf,uint32_t size,void * vaddr)288 int psbWsbmCreateFromUB(void *buf, uint32_t size, void *vaddr)
289 {
290 int ret = 0;
291 struct _WsbmBufferObject *wsbmBuf;
292
293 if (!buf || !vaddr) {
294 ETRACE("invalid parameter");
295 return -EINVAL;
296 }
297
298 wsbmBuf = (struct _WsbmBufferObject *)buf;
299 ret = wsbmBODataUB(wsbmBuf, size, NULL, NULL, 0, vaddr);
300 if (ret) {
301 ETRACE("wsbmBODataUB failed with error code %d", ret);
302 return ret;
303 }
304
305 return 0;
306 }
307
psbWsbmUnReference(void * buf)308 int psbWsbmUnReference(void *buf)
309 {
310 struct _WsbmBufferObject *wsbmBuf;
311
312 if (!buf) {
313 ETRACE("invalid parameter");
314 return -EINVAL;
315 }
316
317 wsbmBuf = (struct _WsbmBufferObject *)buf;
318
319 wsbmBOUnreference(&wsbmBuf);
320
321 return 0;
322 }
323
psbWsbmDestroyTTMBuffer(void * buf)324 int psbWsbmDestroyTTMBuffer(void * buf)
325 {
326 CTRACE();
327
328 if(!buf) {
329 ETRACE("invalid ttm buffer");
330 return -EINVAL;
331 }
332
333 /*FIXME: should I unmap this buffer object first?*/
334 wsbmBOUnmap((struct _WsbmBufferObject *)buf);
335
336 wsbmBOUnreference((struct _WsbmBufferObject **)&buf);
337
338 XTRACE();
339
340 return 0;
341 }
342
psbWsbmGetCPUAddress(void * buf)343 void * psbWsbmGetCPUAddress(void * buf)
344 {
345 if(!buf) {
346 ETRACE("invalid ttm buffer");
347 return NULL;
348 }
349
350 VTRACE("buffer object %p", buf);
351
352 void * address = wsbmBOMap((struct _WsbmBufferObject *)buf,
353 WSBM_ACCESS_READ | WSBM_ACCESS_WRITE);
354 if(!address) {
355 ETRACE("failed to map buffer object");
356 return NULL;
357 }
358
359 VTRACE("mapped successfully. %p, size %ld",
360 address, wsbmBOSize((struct _WsbmBufferObject *)buf));
361
362 return address;
363 }
364
psbWsbmGetGttOffset(void * buf)365 uint32_t psbWsbmGetGttOffset(void * buf)
366 {
367 if(!buf) {
368 ETRACE("invalid ttm buffer");
369 return 0;
370 }
371
372 VTRACE("buffer object %p", buf);
373
374 uint32_t offset =
375 wsbmBOOffsetHint((struct _WsbmBufferObject *)buf) - 0x10000000;
376
377 VTRACE("offset %#x", offset >> 12);
378
379 return offset >> 12;
380 }
381
psbWsbmGetKBufHandle(void * buf)382 uint32_t psbWsbmGetKBufHandle(void *buf)
383 {
384 if (!buf) {
385 ETRACE("invalid ttm buffer");
386 return 0;
387 }
388
389 return (wsbmKBufHandle(wsbmKBuf((struct _WsbmBufferObject *)buf)));
390 }
391
psbWsbmWaitIdle(void * buf)392 uint32_t psbWsbmWaitIdle(void *buf)
393 {
394 if (!buf) {
395 ETRACE("invalid ttm buffer");
396 return -EINVAL;
397 }
398
399 wsbmBOWaitIdle(buf, 0);
400 return 0;
401 }
402