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 unsigned int ioctl_offset = arg.rep.driver_ioctl_offset; 140 ILOGTRACE("ioctl offset %#x", ioctl_offset); 141 142 mainPool = wsbmTTMPoolInit(drmFD, arg.rep.driver_ioctl_offset); 143 if(!mainPool) { 144 ELOGTRACE("failed to initialize TTM Pool"); 145 ret = -EINVAL; 146 goto out; 147 } 148 149 VLOGTRACE("Wsbm initialization succeeded. mainPool %p", mainPool); 150 151 return 0; 152 153 out: 154 psbWsbmTakedown(); 155 return ret; 156 } 157 158 int psbWsbmAllocateFromUB(uint32_t size, uint32_t align, void ** buf, void *user_pt) 159 { 160 struct _WsbmBufferObject * wsbmBuf = NULL; 161 int ret = 0; 162 163 ALOGTRACE("size %d", align_to(size, 4096)); 164 165 if(!buf || !user_pt) { 166 ELOGTRACE("invalid parameter"); 167 return -EINVAL; 168 } 169 170 VLOGTRACE("mainPool %p", mainPool); 171 172 ret = wsbmGenBuffers(mainPool, 1, &wsbmBuf, align, 173 DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_CACHED | 174 WSBM_PL_FLAG_NO_EVICT | WSBM_PL_FLAG_SHARED); 175 if(ret) { 176 ELOGTRACE("wsbmGenBuffers failed with error code %d", ret); 177 return ret; 178 } 179 180 ret = wsbmBODataUB(wsbmBuf, 181 align_to(size, 4096), NULL, NULL, 0, 182 user_pt, -1); 183 184 if(ret) { 185 ELOGTRACE("wsbmBOData failed with error code %d", ret); 186 /*FIXME: should I unreference this buffer here?*/ 187 return ret; 188 } 189 190 *buf = wsbmBuf; 191 192 VLOGTRACE("ttm UB buffer allocated. %p", *buf); 193 return 0; 194 } 195 196 int psbWsbmAllocateTTMBuffer(uint32_t size, uint32_t align, void ** buf) 197 { 198 struct _WsbmBufferObject * wsbmBuf = NULL; 199 int ret = 0; 200 201 ALOGTRACE("size %d", align_to(size, 4096)); 202 203 if(!buf) { 204 ELOGTRACE("invalid parameter"); 205 return -EINVAL; 206 } 207 208 VLOGTRACE("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 ELOGTRACE("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 ELOGTRACE("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 VLOGTRACE("ttm buffer allocated. %p", *buf); 230 return 0; 231 } 232 233 int psbWsbmWrapTTMBuffer(uint32_t handle, void **buf) 234 { 235 int ret = 0; 236 struct _WsbmBufferObject *wsbmBuf; 237 238 if (!buf) { 239 ELOGTRACE("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 ELOGTRACE("wsbmGenBuffers failed with error code %d", ret); 249 return ret; 250 } 251 252 ret = wsbmBOSetReferenced(wsbmBuf, handle); 253 if (ret) { 254 ELOGTRACE("wsbmBOSetReferenced failed with error code %d", ret); 255 return ret; 256 } 257 258 *buf = (void *)wsbmBuf; 259 260 VLOGTRACE("wrap buffer %p for handle %#x", wsbmBuf, handle); 261 return 0; 262 } 263 264 int psbWsbmWrapTTMBuffer2(uint32_t handle, void **buf) 265 { 266 int ret = 0; 267 struct _WsbmBufferObject *wsbmBuf; 268 269 if (!buf) { 270 ELOGTRACE("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 ELOGTRACE("wsbmGenBuffers failed with error code %d", ret); 279 return ret; 280 } 281 282 *buf = (void *)wsbmBuf; 283 284 VLOGTRACE("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 ELOGTRACE("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 ELOGTRACE("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 ELOGTRACE("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 ELOGTRACE("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 XLOGTRACE(); 340 341 return 0; 342 } 343 344 void * psbWsbmGetCPUAddress(void * buf) 345 { 346 if(!buf) { 347 ELOGTRACE("invalid ttm buffer"); 348 return NULL; 349 } 350 351 VLOGTRACE("buffer object %p", buf); 352 353 void * address = wsbmBOMap((struct _WsbmBufferObject *)buf, 354 WSBM_ACCESS_READ | WSBM_ACCESS_WRITE); 355 if(!address) { 356 ELOGTRACE("failed to map buffer object"); 357 return NULL; 358 } 359 360 unsigned long buf_size = wsbmBOSize((struct _WsbmBufferObject *)buf); 361 VLOGTRACE("mapped successfully. %p, size %ld", 362 address, buf_size); 363 364 return address; 365 } 366 367 uint32_t psbWsbmGetGttOffset(void * buf) 368 { 369 if(!buf) { 370 ELOGTRACE("invalid ttm buffer"); 371 return 0; 372 } 373 374 VLOGTRACE("buffer object %p", buf); 375 376 uint32_t offset = 377 wsbmBOOffsetHint((struct _WsbmBufferObject *)buf) - 0x10000000; 378 379 uint32_t offset_tmp = offset >> 12; 380 VLOGTRACE("offset %#x", offset_tmp); 381 382 return offset >> 12; 383 } 384 385 uint32_t psbWsbmGetKBufHandle(void *buf) 386 { 387 if (!buf) { 388 ELOGTRACE("invalid ttm buffer"); 389 return 0; 390 } 391 392 return (wsbmKBufHandle(wsbmKBuf((struct _WsbmBufferObject *)buf))); 393 } 394 395 uint32_t psbWsbmWaitIdle(void *buf) 396 { 397 if (!buf) { 398 ELOGTRACE("invalid ttm buffer"); 399 return -EINVAL; 400 } 401 402 wsbmBOWaitIdle(buf, 0); 403 return 0; 404 } 405