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 <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 35 static inline uint32_t align_to(uint32_t arg, uint32_t align) 36 { 37 return ((arg + (align - 1)) & (~(align - 1))); 38 } 39 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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