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