1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2014 Etnaviv Project 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Christian Gmeiner <christian.gmeiner@gmail.com> 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "os/os_mman.h" 28bf215546Sopenharmony_ci#include "util/hash_table.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "etnaviv_priv.h" 31bf215546Sopenharmony_ci#include "etnaviv_drmif.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_cisimple_mtx_t etna_device_lock = _SIMPLE_MTX_INITIALIZER_NP; 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci/* set buffer name, and add to table, call w/ etna_drm_table_lock held: */ 36bf215546Sopenharmony_cistatic void set_name(struct etna_bo *bo, uint32_t name) 37bf215546Sopenharmony_ci{ 38bf215546Sopenharmony_ci simple_mtx_assert_locked(&etna_device_lock); 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci bo->name = name; 41bf215546Sopenharmony_ci /* add ourself into the name table: */ 42bf215546Sopenharmony_ci _mesa_hash_table_insert(bo->dev->name_table, &bo->name, bo); 43bf215546Sopenharmony_ci} 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ciint etna_bo_is_idle(struct etna_bo *bo) 46bf215546Sopenharmony_ci{ 47bf215546Sopenharmony_ci return etna_bo_cpu_prep(bo, 48bf215546Sopenharmony_ci DRM_ETNA_PREP_READ | 49bf215546Sopenharmony_ci DRM_ETNA_PREP_WRITE | 50bf215546Sopenharmony_ci DRM_ETNA_PREP_NOSYNC) == 0; 51bf215546Sopenharmony_ci} 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci/* Called under etna_drm_table_lock */ 54bf215546Sopenharmony_cistatic void _etna_bo_free(struct etna_bo *bo) 55bf215546Sopenharmony_ci{ 56bf215546Sopenharmony_ci DEBUG_BO("Del bo:", bo); 57bf215546Sopenharmony_ci VG_BO_FREE(bo); 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci simple_mtx_assert_locked(&etna_device_lock); 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci if (bo->va) 62bf215546Sopenharmony_ci util_vma_heap_free(&bo->dev->address_space, bo->va, bo->size); 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci if (bo->map) 65bf215546Sopenharmony_ci os_munmap(bo->map, bo->size); 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci if (bo->handle) { 68bf215546Sopenharmony_ci struct drm_gem_close req = { 69bf215546Sopenharmony_ci .handle = bo->handle, 70bf215546Sopenharmony_ci }; 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci if (bo->name) 73bf215546Sopenharmony_ci _mesa_hash_table_remove_key(bo->dev->name_table, &bo->name); 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci _mesa_hash_table_remove_key(bo->dev->handle_table, &bo->handle); 76bf215546Sopenharmony_ci drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req); 77bf215546Sopenharmony_ci } 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci free(bo); 80bf215546Sopenharmony_ci} 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_civoid etna_bo_kill_zombies(struct etna_device *dev) 83bf215546Sopenharmony_ci{ 84bf215546Sopenharmony_ci simple_mtx_assert_locked(&etna_device_lock); 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci list_for_each_entry_safe(struct etna_bo, bo, &dev->zombie_list, list) { 87bf215546Sopenharmony_ci VG_BO_OBTAIN(bo); 88bf215546Sopenharmony_ci list_del(&bo->list); 89bf215546Sopenharmony_ci _etna_bo_free(bo); 90bf215546Sopenharmony_ci } 91bf215546Sopenharmony_ci} 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_cistatic void etna_bo_cleanup_zombies(struct etna_device *dev) 95bf215546Sopenharmony_ci{ 96bf215546Sopenharmony_ci simple_mtx_assert_locked(&etna_device_lock); 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci list_for_each_entry_safe(struct etna_bo, bo, &dev->zombie_list, list) { 99bf215546Sopenharmony_ci /* Stop once we reach a busy BO - all others past this point were 100bf215546Sopenharmony_ci * freed more recently so are likely also busy. 101bf215546Sopenharmony_ci */ 102bf215546Sopenharmony_ci if (!etna_bo_is_idle(bo)) 103bf215546Sopenharmony_ci break; 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci VG_BO_OBTAIN(bo); 106bf215546Sopenharmony_ci list_del(&bo->list); 107bf215546Sopenharmony_ci _etna_bo_free(bo); 108bf215546Sopenharmony_ci } 109bf215546Sopenharmony_ci} 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_civoid etna_bo_free(struct etna_bo *bo) { 112bf215546Sopenharmony_ci struct etna_device *dev = bo->dev; 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci /* If the BO has a userspace managed address we don't free it immediately, 115bf215546Sopenharmony_ci * but keep it on a deferred destroy list until all submits with the buffer 116bf215546Sopenharmony_ci * have finished, at which point we can reuse the VMA space. 117bf215546Sopenharmony_ci */ 118bf215546Sopenharmony_ci if (dev->use_softpin) { 119bf215546Sopenharmony_ci etna_bo_cleanup_zombies(dev); 120bf215546Sopenharmony_ci VG_BO_RELEASE(bo); 121bf215546Sopenharmony_ci list_addtail(&bo->list, &dev->zombie_list); 122bf215546Sopenharmony_ci } else { 123bf215546Sopenharmony_ci _etna_bo_free(bo); 124bf215546Sopenharmony_ci } 125bf215546Sopenharmony_ci} 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci/* lookup a buffer from it's handle, call w/ etna_drm_table_lock held: */ 128bf215546Sopenharmony_cistatic struct etna_bo *lookup_bo(void *tbl, uint32_t handle) 129bf215546Sopenharmony_ci{ 130bf215546Sopenharmony_ci struct etna_bo *bo = NULL; 131bf215546Sopenharmony_ci struct hash_entry *entry; 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci simple_mtx_assert_locked(&etna_device_lock); 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci entry = _mesa_hash_table_search(tbl, &handle); 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci if (entry) { 138bf215546Sopenharmony_ci /* found, incr refcnt and return: */ 139bf215546Sopenharmony_ci bo = etna_bo_ref(entry->data); 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci /* don't break the bucket if this bo was found in one */ 142bf215546Sopenharmony_ci if (list_is_linked(&bo->list)) { 143bf215546Sopenharmony_ci VG_BO_OBTAIN(bo); 144bf215546Sopenharmony_ci etna_device_ref(bo->dev); 145bf215546Sopenharmony_ci list_delinit(&bo->list); 146bf215546Sopenharmony_ci } 147bf215546Sopenharmony_ci } 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci return bo; 150bf215546Sopenharmony_ci} 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci/* allocate a new buffer object, call w/ etna_drm_table_lock held */ 153bf215546Sopenharmony_cistatic struct etna_bo *bo_from_handle(struct etna_device *dev, 154bf215546Sopenharmony_ci uint32_t size, uint32_t handle, uint32_t flags) 155bf215546Sopenharmony_ci{ 156bf215546Sopenharmony_ci struct etna_bo *bo = calloc(sizeof(*bo), 1); 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci simple_mtx_assert_locked(&etna_device_lock); 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci if (!bo) { 161bf215546Sopenharmony_ci struct drm_gem_close req = { 162bf215546Sopenharmony_ci .handle = handle, 163bf215546Sopenharmony_ci }; 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &req); 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci return NULL; 168bf215546Sopenharmony_ci } 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci bo->dev = etna_device_ref(dev); 171bf215546Sopenharmony_ci bo->size = size; 172bf215546Sopenharmony_ci bo->handle = handle; 173bf215546Sopenharmony_ci bo->flags = flags; 174bf215546Sopenharmony_ci p_atomic_set(&bo->refcnt, 1); 175bf215546Sopenharmony_ci list_inithead(&bo->list); 176bf215546Sopenharmony_ci /* add ourselves to the handle table: */ 177bf215546Sopenharmony_ci _mesa_hash_table_insert(dev->handle_table, &bo->handle, bo); 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci if (dev->use_softpin) 180bf215546Sopenharmony_ci bo->va = util_vma_heap_alloc(&dev->address_space, bo->size, 4096); 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci return bo; 183bf215546Sopenharmony_ci} 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci/* allocate a new (un-tiled) buffer object */ 186bf215546Sopenharmony_cistruct etna_bo *etna_bo_new(struct etna_device *dev, uint32_t size, 187bf215546Sopenharmony_ci uint32_t flags) 188bf215546Sopenharmony_ci{ 189bf215546Sopenharmony_ci struct etna_bo *bo; 190bf215546Sopenharmony_ci int ret; 191bf215546Sopenharmony_ci struct drm_etnaviv_gem_new req = { 192bf215546Sopenharmony_ci .flags = flags, 193bf215546Sopenharmony_ci }; 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci bo = etna_bo_cache_alloc(&dev->bo_cache, &size, flags); 196bf215546Sopenharmony_ci if (bo) 197bf215546Sopenharmony_ci return bo; 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci req.size = size; 200bf215546Sopenharmony_ci ret = drmCommandWriteRead(dev->fd, DRM_ETNAVIV_GEM_NEW, 201bf215546Sopenharmony_ci &req, sizeof(req)); 202bf215546Sopenharmony_ci if (ret) 203bf215546Sopenharmony_ci return NULL; 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci simple_mtx_lock(&etna_device_lock); 206bf215546Sopenharmony_ci bo = bo_from_handle(dev, size, req.handle, flags); 207bf215546Sopenharmony_ci bo->reuse = 1; 208bf215546Sopenharmony_ci simple_mtx_unlock(&etna_device_lock); 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci DEBUG_BO("New bo:", bo); 211bf215546Sopenharmony_ci VG_BO_ALLOC(bo); 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci return bo; 214bf215546Sopenharmony_ci} 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_cistruct etna_bo *etna_bo_ref(struct etna_bo *bo) 217bf215546Sopenharmony_ci{ 218bf215546Sopenharmony_ci p_atomic_inc(&bo->refcnt); 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci return bo; 221bf215546Sopenharmony_ci} 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci/* import a buffer object from DRI2 name */ 224bf215546Sopenharmony_cistruct etna_bo *etna_bo_from_name(struct etna_device *dev, 225bf215546Sopenharmony_ci uint32_t name) 226bf215546Sopenharmony_ci{ 227bf215546Sopenharmony_ci struct etna_bo *bo; 228bf215546Sopenharmony_ci struct drm_gem_open req = { 229bf215546Sopenharmony_ci .name = name, 230bf215546Sopenharmony_ci }; 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci simple_mtx_lock(&etna_device_lock); 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci /* check name table first, to see if bo is already open: */ 235bf215546Sopenharmony_ci bo = lookup_bo(dev->name_table, name); 236bf215546Sopenharmony_ci if (bo) 237bf215546Sopenharmony_ci goto out_unlock; 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) { 240bf215546Sopenharmony_ci ERROR_MSG("gem-open failed: %s", strerror(errno)); 241bf215546Sopenharmony_ci goto out_unlock; 242bf215546Sopenharmony_ci } 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci bo = lookup_bo(dev->handle_table, req.handle); 245bf215546Sopenharmony_ci if (bo) 246bf215546Sopenharmony_ci goto out_unlock; 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci bo = bo_from_handle(dev, req.size, req.handle, 0); 249bf215546Sopenharmony_ci if (bo) { 250bf215546Sopenharmony_ci set_name(bo, name); 251bf215546Sopenharmony_ci DEBUG_BO("New from name:", bo); 252bf215546Sopenharmony_ci VG_BO_ALLOC(bo); 253bf215546Sopenharmony_ci } 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ciout_unlock: 256bf215546Sopenharmony_ci simple_mtx_unlock(&etna_device_lock); 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci return bo; 259bf215546Sopenharmony_ci} 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci/* import a buffer from dmabuf fd, does not take ownership of the 262bf215546Sopenharmony_ci * fd so caller should close() the fd when it is otherwise done 263bf215546Sopenharmony_ci * with it (even if it is still using the 'struct etna_bo *') 264bf215546Sopenharmony_ci */ 265bf215546Sopenharmony_cistruct etna_bo *etna_bo_from_dmabuf(struct etna_device *dev, int fd) 266bf215546Sopenharmony_ci{ 267bf215546Sopenharmony_ci struct etna_bo *bo; 268bf215546Sopenharmony_ci int ret, size; 269bf215546Sopenharmony_ci uint32_t handle; 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_ci /* take the lock before calling drmPrimeFDToHandle to avoid 272bf215546Sopenharmony_ci * racing against etna_bo_del, which might invalidate the 273bf215546Sopenharmony_ci * returned handle. 274bf215546Sopenharmony_ci */ 275bf215546Sopenharmony_ci simple_mtx_lock(&etna_device_lock); 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ci ret = drmPrimeFDToHandle(dev->fd, fd, &handle); 278bf215546Sopenharmony_ci if (ret) { 279bf215546Sopenharmony_ci simple_mtx_unlock(&etna_device_lock); 280bf215546Sopenharmony_ci return NULL; 281bf215546Sopenharmony_ci } 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci bo = lookup_bo(dev->handle_table, handle); 284bf215546Sopenharmony_ci if (bo) 285bf215546Sopenharmony_ci goto out_unlock; 286bf215546Sopenharmony_ci 287bf215546Sopenharmony_ci /* lseek() to get bo size */ 288bf215546Sopenharmony_ci size = lseek(fd, 0, SEEK_END); 289bf215546Sopenharmony_ci lseek(fd, 0, SEEK_CUR); 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci bo = bo_from_handle(dev, size, handle, 0); 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci DEBUG_BO("New from dmabuf:", bo); 294bf215546Sopenharmony_ci VG_BO_ALLOC(bo); 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ciout_unlock: 297bf215546Sopenharmony_ci simple_mtx_unlock(&etna_device_lock); 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci return bo; 300bf215546Sopenharmony_ci} 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci/* destroy a buffer object */ 303bf215546Sopenharmony_civoid etna_bo_del(struct etna_bo *bo) 304bf215546Sopenharmony_ci{ 305bf215546Sopenharmony_ci if (!bo) 306bf215546Sopenharmony_ci return; 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci struct etna_device *dev = bo->dev; 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_ci simple_mtx_lock(&etna_device_lock); 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_ci /* Must test under table lock to avoid racing with the from_dmabuf/name 313bf215546Sopenharmony_ci * paths, which rely on the BO refcount to be stable over the lookup, so 314bf215546Sopenharmony_ci * they can grab a reference when the BO is found in the hash. 315bf215546Sopenharmony_ci */ 316bf215546Sopenharmony_ci if (!p_atomic_dec_zero(&bo->refcnt)) 317bf215546Sopenharmony_ci goto out; 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci if (bo->reuse && (etna_bo_cache_free(&dev->bo_cache, bo) == 0)) 320bf215546Sopenharmony_ci goto out; 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_ci etna_bo_free(bo); 323bf215546Sopenharmony_ci etna_device_del_locked(dev); 324bf215546Sopenharmony_ciout: 325bf215546Sopenharmony_ci simple_mtx_unlock(&etna_device_lock); 326bf215546Sopenharmony_ci} 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci/* get the global flink/DRI2 buffer name */ 329bf215546Sopenharmony_ciint etna_bo_get_name(struct etna_bo *bo, uint32_t *name) 330bf215546Sopenharmony_ci{ 331bf215546Sopenharmony_ci if (!bo->name) { 332bf215546Sopenharmony_ci struct drm_gem_flink req = { 333bf215546Sopenharmony_ci .handle = bo->handle, 334bf215546Sopenharmony_ci }; 335bf215546Sopenharmony_ci int ret; 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req); 338bf215546Sopenharmony_ci if (ret) { 339bf215546Sopenharmony_ci return ret; 340bf215546Sopenharmony_ci } 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci simple_mtx_lock(&etna_device_lock); 343bf215546Sopenharmony_ci set_name(bo, req.name); 344bf215546Sopenharmony_ci simple_mtx_unlock(&etna_device_lock); 345bf215546Sopenharmony_ci bo->reuse = 0; 346bf215546Sopenharmony_ci } 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_ci *name = bo->name; 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci return 0; 351bf215546Sopenharmony_ci} 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_ciuint32_t etna_bo_handle(struct etna_bo *bo) 354bf215546Sopenharmony_ci{ 355bf215546Sopenharmony_ci return bo->handle; 356bf215546Sopenharmony_ci} 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci/* caller owns the dmabuf fd that is returned and is responsible 359bf215546Sopenharmony_ci * to close() it when done 360bf215546Sopenharmony_ci */ 361bf215546Sopenharmony_ciint etna_bo_dmabuf(struct etna_bo *bo) 362bf215546Sopenharmony_ci{ 363bf215546Sopenharmony_ci int ret, prime_fd; 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci ret = drmPrimeHandleToFD(bo->dev->fd, bo->handle, DRM_CLOEXEC, 366bf215546Sopenharmony_ci &prime_fd); 367bf215546Sopenharmony_ci if (ret) { 368bf215546Sopenharmony_ci ERROR_MSG("failed to get dmabuf fd: %d", ret); 369bf215546Sopenharmony_ci return ret; 370bf215546Sopenharmony_ci } 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci bo->reuse = 0; 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci return prime_fd; 375bf215546Sopenharmony_ci} 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_ciuint32_t etna_bo_size(struct etna_bo *bo) 378bf215546Sopenharmony_ci{ 379bf215546Sopenharmony_ci return bo->size; 380bf215546Sopenharmony_ci} 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ciuint32_t etna_bo_gpu_va(struct etna_bo *bo) 383bf215546Sopenharmony_ci{ 384bf215546Sopenharmony_ci return bo->va; 385bf215546Sopenharmony_ci} 386bf215546Sopenharmony_ci 387bf215546Sopenharmony_civoid *etna_bo_map(struct etna_bo *bo) 388bf215546Sopenharmony_ci{ 389bf215546Sopenharmony_ci if (!bo->map) { 390bf215546Sopenharmony_ci int ret; 391bf215546Sopenharmony_ci void *map; 392bf215546Sopenharmony_ci struct drm_etnaviv_gem_info req = { 393bf215546Sopenharmony_ci .handle = bo->handle, 394bf215546Sopenharmony_ci }; 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci ret = drmCommandWriteRead(bo->dev->fd, DRM_ETNAVIV_GEM_INFO, 397bf215546Sopenharmony_ci &req, sizeof(req)); 398bf215546Sopenharmony_ci if (ret) 399bf215546Sopenharmony_ci return NULL; 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_ci map = os_mmap(0, bo->size, PROT_READ | PROT_WRITE, 402bf215546Sopenharmony_ci MAP_SHARED, bo->dev->fd, req.offset); 403bf215546Sopenharmony_ci if (map == MAP_FAILED) { 404bf215546Sopenharmony_ci ERROR_MSG("mmap failed: %s", strerror(errno)); 405bf215546Sopenharmony_ci return NULL; 406bf215546Sopenharmony_ci } 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_ci if (p_atomic_cmpxchg(&bo->map, NULL, map)) 409bf215546Sopenharmony_ci munmap(map, bo->size); 410bf215546Sopenharmony_ci } 411bf215546Sopenharmony_ci 412bf215546Sopenharmony_ci return bo->map; 413bf215546Sopenharmony_ci} 414bf215546Sopenharmony_ci 415bf215546Sopenharmony_ciint etna_bo_cpu_prep(struct etna_bo *bo, uint32_t op) 416bf215546Sopenharmony_ci{ 417bf215546Sopenharmony_ci struct drm_etnaviv_gem_cpu_prep req = { 418bf215546Sopenharmony_ci .handle = bo->handle, 419bf215546Sopenharmony_ci .op = op, 420bf215546Sopenharmony_ci }; 421bf215546Sopenharmony_ci 422bf215546Sopenharmony_ci get_abs_timeout(&req.timeout, 5000000000); 423bf215546Sopenharmony_ci 424bf215546Sopenharmony_ci return drmCommandWrite(bo->dev->fd, DRM_ETNAVIV_GEM_CPU_PREP, 425bf215546Sopenharmony_ci &req, sizeof(req)); 426bf215546Sopenharmony_ci} 427bf215546Sopenharmony_ci 428bf215546Sopenharmony_civoid etna_bo_cpu_fini(struct etna_bo *bo) 429bf215546Sopenharmony_ci{ 430bf215546Sopenharmony_ci struct drm_etnaviv_gem_cpu_fini req = { 431bf215546Sopenharmony_ci .handle = bo->handle, 432bf215546Sopenharmony_ci }; 433bf215546Sopenharmony_ci 434bf215546Sopenharmony_ci drmCommandWrite(bo->dev->fd, DRM_ETNAVIV_GEM_CPU_FINI, 435bf215546Sopenharmony_ci &req, sizeof(req)); 436bf215546Sopenharmony_ci} 437