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 <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 <common/utils/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 34 static inline uint32_t align_to(uint32_t arg, uint32_t align) 35 { 36 return ((arg + (align - 1)) & (~(align - 1))); 37 } 38 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 ELOGTRACE("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 ELOGTRACE("failed to allocate node"); 57 return NULL; 58 } 59 60 node->func = func; 61 node->type_id = 1; 62 return node; 63 } 64 } 65 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 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 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 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 ELOGTRACE("invalid drm fd %d", drmFD); 116 return drmFD; 117 } 118 119 /*init wsbm*/ 120 ret = wsbmInit(wsbmNullThreadFuncs(), &vNodeFuncs); 121 if (ret) { 122 ELOGTRACE("failed to initialize Wsbm, error code %d", ret); 123 return ret; 124 } 125 126 VLOGTRACE("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 ELOGTRACE("failed to get device offset, error code %d", ret); 134 goto out; 135 } 136 137 VLOGTRACE("ioctl offset %#x", arg.rep.driver_ioctl_offset); 138 139 mainPool = wsbmTTMPoolInit(drmFD, arg.rep.driver_ioctl_offset); 140 if(!mainPool) { 141 ELOGTRACE("failed to initialize TTM Pool"); 142 ret = -EINVAL; 143 goto out; 144 } 145 146 VLOGTRACE("Wsbm initialization succeeded. mainPool %p", mainPool); 147 148 return 0; 149 150 out: 151 psbWsbmTakedown(); 152 return ret; 153 } 154 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 ALOGTRACE("size %d", align_to(size, 4096)); 162 163 if(!buf || !user_pt) { 164 ELOGTRACE("invalid parameter"); 165 return -EINVAL; 166 } 167 168 VLOGTRACE("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 ELOGTRACE("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 ELOGTRACE("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 VLOGTRACE("ttm UB buffer allocated. %p", *buf); 191 return 0; 192 } 193 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 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); 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