• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <malloc.h>
18 #include <string.h>
19 #include <wsbm_pool.h>
20 #include <wsbm_driver.h>
21 #include <wsbm_manager.h>
22 #include <wsbm_util.h>
23 #include <drm/ttm/ttm_placement.h>
24 #include <linux/psb_drm.h>
25 #include <xf86drm.h>
26 #include <common/utils/HwcTrace.h>
27 
28 struct _WsbmBufferPool * mainPool = NULL;
29 
30 struct PsbWsbmValidateNode
31 {
32     struct  _ValidateNode base;
33     struct psb_validate_arg arg;
34 };
35 
align_to(uint32_t arg,uint32_t align)36 static inline uint32_t align_to(uint32_t arg, uint32_t align)
37 {
38     return ((arg + (align - 1)) & (~(align - 1)));
39 }
40 
pvrAlloc(struct _WsbmVNodeFuncs * func,int typeId)41 static struct _ValidateNode * pvrAlloc(struct _WsbmVNodeFuncs * func,
42                                        int typeId)
43 {
44     CTRACE();
45     if(typeId == 0) {
46         struct PsbWsbmValidateNode * vNode = malloc(sizeof(*vNode));
47         if(!vNode) {
48             ELOGTRACE("failed to allocate memory");
49             return NULL;
50         }
51 
52         vNode->base.func = func;
53         vNode->base.type_id = 0;
54         return &vNode->base;
55     } else {
56         struct _ValidateNode * node = malloc(sizeof(*node));
57         if(!node) {
58             ELOGTRACE("failed to allocate node");
59             return NULL;
60         }
61 
62         node->func = func;
63         node->type_id = 1;
64         return node;
65     }
66 }
67 
pvrFree(struct _ValidateNode * node)68 static void pvrFree(struct _ValidateNode * node)
69 {
70     CTRACE();
71     if(node->type_id == 0) {
72         free(containerOf(node, struct PsbWsbmValidateNode, base));
73     } else {
74         free(node);
75     }
76 }
77 
pvrClear(struct _ValidateNode * node)78 static void pvrClear(struct _ValidateNode * node)
79 {
80     CTRACE();
81     if(node->type_id == 0) {
82         struct PsbWsbmValidateNode * vNode =
83             containerOf(node, struct PsbWsbmValidateNode, base);
84         memset(&vNode->arg.d.req, 0, sizeof(vNode->arg.d.req));
85     }
86 }
87 
88 static struct _WsbmVNodeFuncs vNodeFuncs = {
89     .alloc  = pvrAlloc,
90     .free   = pvrFree,
91     .clear  = pvrClear,
92 };
93 
psbWsbmTakedown()94 void psbWsbmTakedown()
95 {
96     CTRACE();
97 
98     if (mainPool) {
99         wsbmPoolTakeDown(mainPool);
100         mainPool = NULL;
101     }
102 
103     if (wsbmIsInitialized()) {
104         wsbmTakedown();
105     }
106 }
107 
psbWsbmInitialize(int drmFD)108 int psbWsbmInitialize(int drmFD)
109 {
110     union drm_psb_extension_arg arg;
111     const char drmExt[] = "psb_ttm_placement_alphadrop";
112     int ret = 0;
113 
114     CTRACE();
115 
116     if (drmFD <= 0) {
117         ELOGTRACE("invalid drm fd %d", drmFD);
118         return drmFD;
119     }
120 
121     /*init wsbm*/
122     ret = wsbmInit(wsbmNullThreadFuncs(), &vNodeFuncs);
123     if (ret) {
124         ELOGTRACE("failed to initialize Wsbm, error code %d", ret);
125         return ret;
126     }
127 
128     VLOGTRACE("DRM_PSB_EXTENSION %d", DRM_PSB_EXTENSION);
129 
130     /*get devOffset via drm IOCTL*/
131     strncpy(arg.extension, drmExt, sizeof(drmExt));
132 
133     ret = drmCommandWriteRead(drmFD, 6/*DRM_PSB_EXTENSION*/, &arg, sizeof(arg));
134     if(ret || !arg.rep.exists) {
135         ELOGTRACE("failed to get device offset, error code %d", ret);
136         goto out;
137     }
138 
139     VLOGTRACE("ioctl offset %#x", arg.rep.driver_ioctl_offset);
140 
141     mainPool = wsbmTTMPoolInit(drmFD, arg.rep.driver_ioctl_offset);
142     if(!mainPool) {
143         ELOGTRACE("failed to initialize TTM Pool");
144         ret = -EINVAL;
145         goto out;
146     }
147 
148     VLOGTRACE("Wsbm initialization succeeded. mainPool %p", mainPool);
149 
150     return 0;
151 
152 out:
153     psbWsbmTakedown();
154     return ret;
155 }
156 
psbWsbmAllocateFromUB(uint32_t size,uint32_t align,void ** buf,void * user_pt)157 int psbWsbmAllocateFromUB(uint32_t size, uint32_t align, void ** buf, void *user_pt)
158 {
159     struct _WsbmBufferObject * wsbmBuf = NULL;
160     int ret = 0;
161 
162     ALOGTRACE("size %d", align_to(size, 4096));
163 
164     if(!buf || !user_pt) {
165         ELOGTRACE("invalid parameter");
166         return -EINVAL;
167     }
168 
169     VLOGTRACE("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         ELOGTRACE("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         ELOGTRACE("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     VLOGTRACE("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 
200     ALOGTRACE("size %d", align_to(size, 4096));
201 
202     if(!buf) {
203         ELOGTRACE("invalid parameter");
204         return -EINVAL;
205     }
206 
207     VLOGTRACE("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         ELOGTRACE("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         ELOGTRACE("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     VLOGTRACE("ttm buffer allocated. %p", *buf);
229     return 0;
230 }
231 
psbWsbmWrapTTMBuffer(uint32_t handle,void ** buf)232 int psbWsbmWrapTTMBuffer(uint32_t handle, void **buf)
233 {
234     int ret = 0;
235     struct _WsbmBufferObject *wsbmBuf;
236 
237     if (!buf) {
238         ELOGTRACE("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         ELOGTRACE("wsbmGenBuffers failed with error code %d", ret);
248         return ret;
249     }
250 
251     ret = wsbmBOSetReferenced(wsbmBuf, handle);
252     if (ret) {
253         ELOGTRACE("wsbmBOSetReferenced failed with error code %d", ret);
254         return ret;
255     }
256 
257     *buf = (void *)wsbmBuf;
258 
259     VLOGTRACE("wrap buffer %p for handle %#x", wsbmBuf, handle);
260     return 0;
261 }
262 
psbWsbmWrapTTMBuffer2(uint32_t handle,void ** buf)263 int psbWsbmWrapTTMBuffer2(uint32_t handle, void **buf)
264 {
265     int ret = 0;
266     struct _WsbmBufferObject *wsbmBuf;
267 
268     if (!buf) {
269         ELOGTRACE("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         ELOGTRACE("wsbmGenBuffers failed with error code %d", ret);
278         return ret;
279     }
280 
281     *buf = (void *)wsbmBuf;
282 
283     VLOGTRACE("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         ELOGTRACE("invalid parameter");
295         return -EINVAL;
296     }
297 
298     wsbmBuf = (struct _WsbmBufferObject *)buf;
299     ret = wsbmBODataUB(wsbmBuf, size, NULL, NULL, 0, vaddr, -1);
300     if (ret) {
301         ELOGTRACE("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         ELOGTRACE("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         ELOGTRACE("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     XLOGTRACE();
339 
340     return 0;
341 }
342 
psbWsbmGetCPUAddress(void * buf)343 void * psbWsbmGetCPUAddress(void * buf)
344 {
345     if(!buf) {
346         ELOGTRACE("invalid ttm buffer");
347         return NULL;
348     }
349 
350     VLOGTRACE("buffer object %p", buf);
351 
352     void * address = wsbmBOMap((struct _WsbmBufferObject *)buf,
353                                 WSBM_ACCESS_READ | WSBM_ACCESS_WRITE);
354     if(!address) {
355         ELOGTRACE("failed to map buffer object");
356         return NULL;
357     }
358 
359     VLOGTRACE("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         ELOGTRACE("invalid ttm buffer");
369         return 0;
370     }
371 
372     VLOGTRACE("buffer object %p", buf);
373 
374     uint32_t offset =
375         wsbmBOOffsetHint((struct _WsbmBufferObject *)buf) - 0x10000000;
376 
377     VLOGTRACE("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         ELOGTRACE("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         ELOGTRACE("invalid ttm buffer");
396         return -EINVAL;
397     }
398 
399     wsbmBOWaitIdle(buf, 0);
400     return 0;
401 }
402