1 /* 2 // Copyright(c)2014 IntelCorporation 3 // 4 // LicensedundertheApacheLicense,Version2.0(the"License"); 5 // youmaynotusethisfileexceptincompliancewiththeLicense. 6 // YoumayobtainacopyoftheLicenseat 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unlessrequiredbyapplicablelaworagreedtoinwriting,software 11 // distributedundertheLicenseisdistributedonan"ASIS"BASIS, 12 // WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied. 13 // SeetheLicenseforthespecificlanguagegoverningpermissionsand 14 // limitationsundertheLicense. 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 36 static inline uint32_t align_to(uint32_t arg, uint32_t align) 37 { 38 return ((arg + (align - 1)) & (~(align - 1))); 39 } 40 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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