• 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 <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