1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2017-2019 Lima 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 shall be included in 12bf215546Sopenharmony_ci * all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci * 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include <stdlib.h> 25bf215546Sopenharmony_ci#include <sys/types.h> 26bf215546Sopenharmony_ci#include <unistd.h> 27bf215546Sopenharmony_ci#include <fcntl.h> 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "xf86drm.h" 30bf215546Sopenharmony_ci#include "drm-uapi/lima_drm.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "util/u_hash_table.h" 33bf215546Sopenharmony_ci#include "util/u_math.h" 34bf215546Sopenharmony_ci#include "util/os_time.h" 35bf215546Sopenharmony_ci#include "os/os_mman.h" 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci#include "frontend/drm_driver.h" 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci#include "lima_screen.h" 40bf215546Sopenharmony_ci#include "lima_bo.h" 41bf215546Sopenharmony_ci#include "lima_util.h" 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_cibool lima_bo_table_init(struct lima_screen *screen) 44bf215546Sopenharmony_ci{ 45bf215546Sopenharmony_ci screen->bo_handles = util_hash_table_create_ptr_keys(); 46bf215546Sopenharmony_ci if (!screen->bo_handles) 47bf215546Sopenharmony_ci return false; 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci screen->bo_flink_names = util_hash_table_create_ptr_keys(); 50bf215546Sopenharmony_ci if (!screen->bo_flink_names) 51bf215546Sopenharmony_ci goto err_out0; 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci mtx_init(&screen->bo_table_lock, mtx_plain); 54bf215546Sopenharmony_ci return true; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_cierr_out0: 57bf215546Sopenharmony_ci _mesa_hash_table_destroy(screen->bo_handles, NULL); 58bf215546Sopenharmony_ci return false; 59bf215546Sopenharmony_ci} 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_cibool lima_bo_cache_init(struct lima_screen *screen) 62bf215546Sopenharmony_ci{ 63bf215546Sopenharmony_ci mtx_init(&screen->bo_cache_lock, mtx_plain); 64bf215546Sopenharmony_ci list_inithead(&screen->bo_cache_time); 65bf215546Sopenharmony_ci for (int i = 0; i < NR_BO_CACHE_BUCKETS; i++) 66bf215546Sopenharmony_ci list_inithead(&screen->bo_cache_buckets[i]); 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci return true; 69bf215546Sopenharmony_ci} 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_civoid lima_bo_table_fini(struct lima_screen *screen) 72bf215546Sopenharmony_ci{ 73bf215546Sopenharmony_ci mtx_destroy(&screen->bo_table_lock); 74bf215546Sopenharmony_ci _mesa_hash_table_destroy(screen->bo_handles, NULL); 75bf215546Sopenharmony_ci _mesa_hash_table_destroy(screen->bo_flink_names, NULL); 76bf215546Sopenharmony_ci} 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_cistatic void 79bf215546Sopenharmony_cilima_bo_cache_remove(struct lima_bo *bo) 80bf215546Sopenharmony_ci{ 81bf215546Sopenharmony_ci list_del(&bo->size_list); 82bf215546Sopenharmony_ci list_del(&bo->time_list); 83bf215546Sopenharmony_ci} 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_cistatic void lima_close_kms_handle(struct lima_screen *screen, uint32_t handle) 86bf215546Sopenharmony_ci{ 87bf215546Sopenharmony_ci struct drm_gem_close args = { 88bf215546Sopenharmony_ci .handle = handle, 89bf215546Sopenharmony_ci }; 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci drmIoctl(screen->fd, DRM_IOCTL_GEM_CLOSE, &args); 92bf215546Sopenharmony_ci} 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_cistatic void 95bf215546Sopenharmony_cilima_bo_free(struct lima_bo *bo) 96bf215546Sopenharmony_ci{ 97bf215546Sopenharmony_ci struct lima_screen *screen = bo->screen; 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci if (lima_debug & LIMA_DEBUG_BO_CACHE) 100bf215546Sopenharmony_ci fprintf(stderr, "%s: %p (size=%d)\n", __func__, 101bf215546Sopenharmony_ci bo, bo->size); 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci mtx_lock(&screen->bo_table_lock); 104bf215546Sopenharmony_ci _mesa_hash_table_remove_key(screen->bo_handles, 105bf215546Sopenharmony_ci (void *)(uintptr_t)bo->handle); 106bf215546Sopenharmony_ci if (bo->flink_name) 107bf215546Sopenharmony_ci _mesa_hash_table_remove_key(screen->bo_flink_names, 108bf215546Sopenharmony_ci (void *)(uintptr_t)bo->flink_name); 109bf215546Sopenharmony_ci mtx_unlock(&screen->bo_table_lock); 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci if (bo->map) 112bf215546Sopenharmony_ci lima_bo_unmap(bo); 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci lima_close_kms_handle(screen, bo->handle); 115bf215546Sopenharmony_ci free(bo); 116bf215546Sopenharmony_ci} 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_civoid lima_bo_cache_fini(struct lima_screen *screen) 119bf215546Sopenharmony_ci{ 120bf215546Sopenharmony_ci mtx_destroy(&screen->bo_cache_lock); 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci list_for_each_entry_safe(struct lima_bo, entry, 123bf215546Sopenharmony_ci &screen->bo_cache_time, time_list) { 124bf215546Sopenharmony_ci lima_bo_cache_remove(entry); 125bf215546Sopenharmony_ci lima_bo_free(entry); 126bf215546Sopenharmony_ci } 127bf215546Sopenharmony_ci} 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_cistatic bool lima_bo_get_info(struct lima_bo *bo) 130bf215546Sopenharmony_ci{ 131bf215546Sopenharmony_ci struct drm_lima_gem_info req = { 132bf215546Sopenharmony_ci .handle = bo->handle, 133bf215546Sopenharmony_ci }; 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci if(drmIoctl(bo->screen->fd, DRM_IOCTL_LIMA_GEM_INFO, &req)) 136bf215546Sopenharmony_ci return false; 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci bo->offset = req.offset; 139bf215546Sopenharmony_ci bo->va = req.va; 140bf215546Sopenharmony_ci return true; 141bf215546Sopenharmony_ci} 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_cistatic unsigned 144bf215546Sopenharmony_cilima_bucket_index(unsigned size) 145bf215546Sopenharmony_ci{ 146bf215546Sopenharmony_ci /* Round down to POT to compute a bucket index */ 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci unsigned bucket_index = util_logbase2(size); 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci /* Clamp the bucket index; all huge allocations will be 151bf215546Sopenharmony_ci * sorted into the largest bucket */ 152bf215546Sopenharmony_ci bucket_index = CLAMP(bucket_index, MIN_BO_CACHE_BUCKET, 153bf215546Sopenharmony_ci MAX_BO_CACHE_BUCKET); 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci /* Reindex from 0 */ 156bf215546Sopenharmony_ci return (bucket_index - MIN_BO_CACHE_BUCKET); 157bf215546Sopenharmony_ci} 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_cistatic struct list_head * 160bf215546Sopenharmony_cilima_bo_cache_get_bucket(struct lima_screen *screen, unsigned size) 161bf215546Sopenharmony_ci{ 162bf215546Sopenharmony_ci return &screen->bo_cache_buckets[lima_bucket_index(size)]; 163bf215546Sopenharmony_ci} 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_cistatic void 166bf215546Sopenharmony_cilima_bo_cache_free_stale_bos(struct lima_screen *screen, time_t time) 167bf215546Sopenharmony_ci{ 168bf215546Sopenharmony_ci unsigned cnt = 0; 169bf215546Sopenharmony_ci list_for_each_entry_safe(struct lima_bo, entry, 170bf215546Sopenharmony_ci &screen->bo_cache_time, time_list) { 171bf215546Sopenharmony_ci /* Free BOs that are sitting idle for longer than 5 seconds */ 172bf215546Sopenharmony_ci if (time - entry->free_time > 6) { 173bf215546Sopenharmony_ci lima_bo_cache_remove(entry); 174bf215546Sopenharmony_ci lima_bo_free(entry); 175bf215546Sopenharmony_ci cnt++; 176bf215546Sopenharmony_ci } else 177bf215546Sopenharmony_ci break; 178bf215546Sopenharmony_ci } 179bf215546Sopenharmony_ci if ((lima_debug & LIMA_DEBUG_BO_CACHE) && cnt) 180bf215546Sopenharmony_ci fprintf(stderr, "%s: freed %d stale BOs\n", __func__, cnt); 181bf215546Sopenharmony_ci} 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_cistatic void 184bf215546Sopenharmony_cilima_bo_cache_print_stats(struct lima_screen *screen) 185bf215546Sopenharmony_ci{ 186bf215546Sopenharmony_ci fprintf(stderr, "===============\n"); 187bf215546Sopenharmony_ci fprintf(stderr, "BO cache stats:\n"); 188bf215546Sopenharmony_ci unsigned total_size = 0; 189bf215546Sopenharmony_ci for (int i = 0; i < NR_BO_CACHE_BUCKETS; i++) { 190bf215546Sopenharmony_ci struct list_head *bucket = &screen->bo_cache_buckets[i]; 191bf215546Sopenharmony_ci unsigned bucket_size = 0; 192bf215546Sopenharmony_ci list_for_each_entry(struct lima_bo, entry, bucket, size_list) { 193bf215546Sopenharmony_ci bucket_size += entry->size; 194bf215546Sopenharmony_ci total_size += entry->size; 195bf215546Sopenharmony_ci } 196bf215546Sopenharmony_ci fprintf(stderr, "Bucket #%d, BOs: %d, size: %u\n", i, 197bf215546Sopenharmony_ci list_length(bucket), 198bf215546Sopenharmony_ci bucket_size); 199bf215546Sopenharmony_ci } 200bf215546Sopenharmony_ci fprintf(stderr, "Total size: %u\n", total_size); 201bf215546Sopenharmony_ci} 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_cistatic bool 204bf215546Sopenharmony_cilima_bo_cache_put(struct lima_bo *bo) 205bf215546Sopenharmony_ci{ 206bf215546Sopenharmony_ci if (!bo->cacheable) 207bf215546Sopenharmony_ci return false; 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci struct lima_screen *screen = bo->screen; 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci mtx_lock(&screen->bo_cache_lock); 212bf215546Sopenharmony_ci struct list_head *bucket = lima_bo_cache_get_bucket(screen, bo->size); 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci if (!bucket) { 215bf215546Sopenharmony_ci mtx_unlock(&screen->bo_cache_lock); 216bf215546Sopenharmony_ci return false; 217bf215546Sopenharmony_ci } 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci struct timespec time; 220bf215546Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &time); 221bf215546Sopenharmony_ci bo->free_time = time.tv_sec; 222bf215546Sopenharmony_ci list_addtail(&bo->size_list, bucket); 223bf215546Sopenharmony_ci list_addtail(&bo->time_list, &screen->bo_cache_time); 224bf215546Sopenharmony_ci lima_bo_cache_free_stale_bos(screen, time.tv_sec); 225bf215546Sopenharmony_ci if (lima_debug & LIMA_DEBUG_BO_CACHE) { 226bf215546Sopenharmony_ci fprintf(stderr, "%s: put BO: %p (size=%d)\n", __func__, bo, bo->size); 227bf215546Sopenharmony_ci lima_bo_cache_print_stats(screen); 228bf215546Sopenharmony_ci } 229bf215546Sopenharmony_ci mtx_unlock(&screen->bo_cache_lock); 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci return true; 232bf215546Sopenharmony_ci} 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_cistatic struct lima_bo * 235bf215546Sopenharmony_cilima_bo_cache_get(struct lima_screen *screen, uint32_t size, uint32_t flags) 236bf215546Sopenharmony_ci{ 237bf215546Sopenharmony_ci /* we won't cache heap buffer */ 238bf215546Sopenharmony_ci if (flags & LIMA_BO_FLAG_HEAP) 239bf215546Sopenharmony_ci return NULL; 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci struct lima_bo *bo = NULL; 242bf215546Sopenharmony_ci mtx_lock(&screen->bo_cache_lock); 243bf215546Sopenharmony_ci struct list_head *bucket = lima_bo_cache_get_bucket(screen, size); 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci if (!bucket) { 246bf215546Sopenharmony_ci mtx_unlock(&screen->bo_cache_lock); 247bf215546Sopenharmony_ci return false; 248bf215546Sopenharmony_ci } 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci list_for_each_entry_safe(struct lima_bo, entry, bucket, size_list) { 251bf215546Sopenharmony_ci if (entry->size >= size) { 252bf215546Sopenharmony_ci /* Check if BO is idle. If it's not it's better to allocate new one */ 253bf215546Sopenharmony_ci if (!lima_bo_wait(entry, LIMA_GEM_WAIT_WRITE, 0)) { 254bf215546Sopenharmony_ci if (lima_debug & LIMA_DEBUG_BO_CACHE) { 255bf215546Sopenharmony_ci fprintf(stderr, "%s: found BO %p but it's busy\n", __func__, 256bf215546Sopenharmony_ci entry); 257bf215546Sopenharmony_ci } 258bf215546Sopenharmony_ci break; 259bf215546Sopenharmony_ci } 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci lima_bo_cache_remove(entry); 262bf215546Sopenharmony_ci p_atomic_set(&entry->refcnt, 1); 263bf215546Sopenharmony_ci entry->flags = flags; 264bf215546Sopenharmony_ci bo = entry; 265bf215546Sopenharmony_ci if (lima_debug & LIMA_DEBUG_BO_CACHE) { 266bf215546Sopenharmony_ci fprintf(stderr, "%s: got BO: %p (size=%d), requested size %d\n", 267bf215546Sopenharmony_ci __func__, bo, bo->size, size); 268bf215546Sopenharmony_ci lima_bo_cache_print_stats(screen); 269bf215546Sopenharmony_ci } 270bf215546Sopenharmony_ci break; 271bf215546Sopenharmony_ci } 272bf215546Sopenharmony_ci } 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci mtx_unlock(&screen->bo_cache_lock); 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci return bo; 277bf215546Sopenharmony_ci} 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_cistruct lima_bo *lima_bo_create(struct lima_screen *screen, 280bf215546Sopenharmony_ci uint32_t size, uint32_t flags) 281bf215546Sopenharmony_ci{ 282bf215546Sopenharmony_ci struct lima_bo *bo; 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci size = align(size, LIMA_PAGE_SIZE); 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci /* Try to get bo from cache first */ 287bf215546Sopenharmony_ci bo = lima_bo_cache_get(screen, size, flags); 288bf215546Sopenharmony_ci if (bo) 289bf215546Sopenharmony_ci return bo; 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci struct drm_lima_gem_create req = { 292bf215546Sopenharmony_ci .size = size, 293bf215546Sopenharmony_ci .flags = flags, 294bf215546Sopenharmony_ci }; 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci if (!(bo = calloc(1, sizeof(*bo)))) 297bf215546Sopenharmony_ci return NULL; 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci list_inithead(&bo->time_list); 300bf215546Sopenharmony_ci list_inithead(&bo->size_list); 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci if (drmIoctl(screen->fd, DRM_IOCTL_LIMA_GEM_CREATE, &req)) 303bf215546Sopenharmony_ci goto err_out0; 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci bo->screen = screen; 306bf215546Sopenharmony_ci bo->size = req.size; 307bf215546Sopenharmony_ci bo->flags = req.flags; 308bf215546Sopenharmony_ci bo->handle = req.handle; 309bf215546Sopenharmony_ci bo->cacheable = !(lima_debug & LIMA_DEBUG_NO_BO_CACHE || 310bf215546Sopenharmony_ci flags & LIMA_BO_FLAG_HEAP); 311bf215546Sopenharmony_ci p_atomic_set(&bo->refcnt, 1); 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci if (!lima_bo_get_info(bo)) 314bf215546Sopenharmony_ci goto err_out1; 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci if (lima_debug & LIMA_DEBUG_BO_CACHE) 317bf215546Sopenharmony_ci fprintf(stderr, "%s: %p (size=%d)\n", __func__, 318bf215546Sopenharmony_ci bo, bo->size); 319bf215546Sopenharmony_ci 320bf215546Sopenharmony_ci return bo; 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_cierr_out1: 323bf215546Sopenharmony_ci lima_close_kms_handle(screen, bo->handle); 324bf215546Sopenharmony_cierr_out0: 325bf215546Sopenharmony_ci free(bo); 326bf215546Sopenharmony_ci return NULL; 327bf215546Sopenharmony_ci} 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_civoid lima_bo_unreference(struct lima_bo *bo) 330bf215546Sopenharmony_ci{ 331bf215546Sopenharmony_ci if (!p_atomic_dec_zero(&bo->refcnt)) 332bf215546Sopenharmony_ci return; 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci /* Try to put it into cache */ 335bf215546Sopenharmony_ci if (lima_bo_cache_put(bo)) 336bf215546Sopenharmony_ci return; 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci lima_bo_free(bo); 339bf215546Sopenharmony_ci} 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_civoid *lima_bo_map(struct lima_bo *bo) 342bf215546Sopenharmony_ci{ 343bf215546Sopenharmony_ci if (!bo->map) { 344bf215546Sopenharmony_ci bo->map = os_mmap(0, bo->size, PROT_READ | PROT_WRITE, 345bf215546Sopenharmony_ci MAP_SHARED, bo->screen->fd, bo->offset); 346bf215546Sopenharmony_ci if (bo->map == MAP_FAILED) 347bf215546Sopenharmony_ci bo->map = NULL; 348bf215546Sopenharmony_ci } 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci return bo->map; 351bf215546Sopenharmony_ci} 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_civoid lima_bo_unmap(struct lima_bo *bo) 354bf215546Sopenharmony_ci{ 355bf215546Sopenharmony_ci if (bo->map) { 356bf215546Sopenharmony_ci os_munmap(bo->map, bo->size); 357bf215546Sopenharmony_ci bo->map = NULL; 358bf215546Sopenharmony_ci } 359bf215546Sopenharmony_ci} 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_cibool lima_bo_export(struct lima_bo *bo, struct winsys_handle *handle) 362bf215546Sopenharmony_ci{ 363bf215546Sopenharmony_ci struct lima_screen *screen = bo->screen; 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci /* Don't cache exported BOs */ 366bf215546Sopenharmony_ci bo->cacheable = false; 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_ci switch (handle->type) { 369bf215546Sopenharmony_ci case WINSYS_HANDLE_TYPE_SHARED: 370bf215546Sopenharmony_ci if (!bo->flink_name) { 371bf215546Sopenharmony_ci struct drm_gem_flink flink = { 372bf215546Sopenharmony_ci .handle = bo->handle, 373bf215546Sopenharmony_ci .name = 0, 374bf215546Sopenharmony_ci }; 375bf215546Sopenharmony_ci if (drmIoctl(screen->fd, DRM_IOCTL_GEM_FLINK, &flink)) 376bf215546Sopenharmony_ci return false; 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_ci bo->flink_name = flink.name; 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci mtx_lock(&screen->bo_table_lock); 381bf215546Sopenharmony_ci _mesa_hash_table_insert(screen->bo_flink_names, 382bf215546Sopenharmony_ci (void *)(uintptr_t)bo->flink_name, bo); 383bf215546Sopenharmony_ci mtx_unlock(&screen->bo_table_lock); 384bf215546Sopenharmony_ci } 385bf215546Sopenharmony_ci handle->handle = bo->flink_name; 386bf215546Sopenharmony_ci return true; 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci case WINSYS_HANDLE_TYPE_KMS: 389bf215546Sopenharmony_ci mtx_lock(&screen->bo_table_lock); 390bf215546Sopenharmony_ci _mesa_hash_table_insert(screen->bo_handles, 391bf215546Sopenharmony_ci (void *)(uintptr_t)bo->handle, bo); 392bf215546Sopenharmony_ci mtx_unlock(&screen->bo_table_lock); 393bf215546Sopenharmony_ci 394bf215546Sopenharmony_ci handle->handle = bo->handle; 395bf215546Sopenharmony_ci return true; 396bf215546Sopenharmony_ci 397bf215546Sopenharmony_ci case WINSYS_HANDLE_TYPE_FD: 398bf215546Sopenharmony_ci if (drmPrimeHandleToFD(screen->fd, bo->handle, DRM_CLOEXEC, 399bf215546Sopenharmony_ci (int*)&handle->handle)) 400bf215546Sopenharmony_ci return false; 401bf215546Sopenharmony_ci 402bf215546Sopenharmony_ci mtx_lock(&screen->bo_table_lock); 403bf215546Sopenharmony_ci _mesa_hash_table_insert(screen->bo_handles, 404bf215546Sopenharmony_ci (void *)(uintptr_t)bo->handle, bo); 405bf215546Sopenharmony_ci mtx_unlock(&screen->bo_table_lock); 406bf215546Sopenharmony_ci return true; 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_ci default: 409bf215546Sopenharmony_ci return false; 410bf215546Sopenharmony_ci } 411bf215546Sopenharmony_ci} 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_cistruct lima_bo *lima_bo_import(struct lima_screen *screen, 414bf215546Sopenharmony_ci struct winsys_handle *handle) 415bf215546Sopenharmony_ci{ 416bf215546Sopenharmony_ci struct lima_bo *bo = NULL; 417bf215546Sopenharmony_ci struct drm_gem_open req = {0}; 418bf215546Sopenharmony_ci uint32_t dma_buf_size = 0; 419bf215546Sopenharmony_ci unsigned h = handle->handle; 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_ci mtx_lock(&screen->bo_table_lock); 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci /* Convert a DMA buf handle to a KMS handle now. */ 424bf215546Sopenharmony_ci if (handle->type == WINSYS_HANDLE_TYPE_FD) { 425bf215546Sopenharmony_ci uint32_t prime_handle; 426bf215546Sopenharmony_ci off_t size; 427bf215546Sopenharmony_ci 428bf215546Sopenharmony_ci /* Get a KMS handle. */ 429bf215546Sopenharmony_ci if (drmPrimeFDToHandle(screen->fd, h, &prime_handle)) { 430bf215546Sopenharmony_ci mtx_unlock(&screen->bo_table_lock); 431bf215546Sopenharmony_ci return NULL; 432bf215546Sopenharmony_ci } 433bf215546Sopenharmony_ci 434bf215546Sopenharmony_ci /* Query the buffer size. */ 435bf215546Sopenharmony_ci size = lseek(h, 0, SEEK_END); 436bf215546Sopenharmony_ci if (size == (off_t)-1) { 437bf215546Sopenharmony_ci mtx_unlock(&screen->bo_table_lock); 438bf215546Sopenharmony_ci lima_close_kms_handle(screen, prime_handle); 439bf215546Sopenharmony_ci return NULL; 440bf215546Sopenharmony_ci } 441bf215546Sopenharmony_ci lseek(h, 0, SEEK_SET); 442bf215546Sopenharmony_ci 443bf215546Sopenharmony_ci dma_buf_size = size; 444bf215546Sopenharmony_ci h = prime_handle; 445bf215546Sopenharmony_ci } 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci switch (handle->type) { 448bf215546Sopenharmony_ci case WINSYS_HANDLE_TYPE_SHARED: 449bf215546Sopenharmony_ci bo = util_hash_table_get(screen->bo_flink_names, 450bf215546Sopenharmony_ci (void *)(uintptr_t)h); 451bf215546Sopenharmony_ci break; 452bf215546Sopenharmony_ci case WINSYS_HANDLE_TYPE_KMS: 453bf215546Sopenharmony_ci case WINSYS_HANDLE_TYPE_FD: 454bf215546Sopenharmony_ci bo = util_hash_table_get(screen->bo_handles, 455bf215546Sopenharmony_ci (void *)(uintptr_t)h); 456bf215546Sopenharmony_ci break; 457bf215546Sopenharmony_ci default: 458bf215546Sopenharmony_ci mtx_unlock(&screen->bo_table_lock); 459bf215546Sopenharmony_ci return NULL; 460bf215546Sopenharmony_ci } 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci if (bo) { 463bf215546Sopenharmony_ci p_atomic_inc(&bo->refcnt); 464bf215546Sopenharmony_ci /* Don't cache imported BOs */ 465bf215546Sopenharmony_ci bo->cacheable = false; 466bf215546Sopenharmony_ci mtx_unlock(&screen->bo_table_lock); 467bf215546Sopenharmony_ci return bo; 468bf215546Sopenharmony_ci } 469bf215546Sopenharmony_ci 470bf215546Sopenharmony_ci if (!(bo = calloc(1, sizeof(*bo)))) { 471bf215546Sopenharmony_ci mtx_unlock(&screen->bo_table_lock); 472bf215546Sopenharmony_ci if (handle->type == WINSYS_HANDLE_TYPE_FD) 473bf215546Sopenharmony_ci lima_close_kms_handle(screen, h); 474bf215546Sopenharmony_ci return NULL; 475bf215546Sopenharmony_ci } 476bf215546Sopenharmony_ci 477bf215546Sopenharmony_ci /* Don't cache imported BOs */ 478bf215546Sopenharmony_ci bo->cacheable = false; 479bf215546Sopenharmony_ci list_inithead(&bo->time_list); 480bf215546Sopenharmony_ci list_inithead(&bo->size_list); 481bf215546Sopenharmony_ci bo->screen = screen; 482bf215546Sopenharmony_ci p_atomic_set(&bo->refcnt, 1); 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci switch (handle->type) { 485bf215546Sopenharmony_ci case WINSYS_HANDLE_TYPE_SHARED: 486bf215546Sopenharmony_ci req.name = h; 487bf215546Sopenharmony_ci if (drmIoctl(screen->fd, DRM_IOCTL_GEM_OPEN, &req)) { 488bf215546Sopenharmony_ci mtx_unlock(&screen->bo_table_lock); 489bf215546Sopenharmony_ci free(bo); 490bf215546Sopenharmony_ci return NULL; 491bf215546Sopenharmony_ci } 492bf215546Sopenharmony_ci bo->handle = req.handle; 493bf215546Sopenharmony_ci bo->flink_name = h; 494bf215546Sopenharmony_ci bo->size = req.size; 495bf215546Sopenharmony_ci break; 496bf215546Sopenharmony_ci case WINSYS_HANDLE_TYPE_FD: 497bf215546Sopenharmony_ci bo->handle = h; 498bf215546Sopenharmony_ci bo->size = dma_buf_size; 499bf215546Sopenharmony_ci break; 500bf215546Sopenharmony_ci default: 501bf215546Sopenharmony_ci /* not possible */ 502bf215546Sopenharmony_ci assert(0); 503bf215546Sopenharmony_ci } 504bf215546Sopenharmony_ci 505bf215546Sopenharmony_ci if (lima_bo_get_info(bo)) { 506bf215546Sopenharmony_ci if (handle->type == WINSYS_HANDLE_TYPE_SHARED) 507bf215546Sopenharmony_ci _mesa_hash_table_insert(screen->bo_flink_names, 508bf215546Sopenharmony_ci (void *)(uintptr_t)bo->flink_name, bo); 509bf215546Sopenharmony_ci _mesa_hash_table_insert(screen->bo_handles, 510bf215546Sopenharmony_ci (void*)(uintptr_t)bo->handle, bo); 511bf215546Sopenharmony_ci } 512bf215546Sopenharmony_ci else { 513bf215546Sopenharmony_ci lima_close_kms_handle(screen, bo->handle); 514bf215546Sopenharmony_ci free(bo); 515bf215546Sopenharmony_ci bo = NULL; 516bf215546Sopenharmony_ci } 517bf215546Sopenharmony_ci 518bf215546Sopenharmony_ci mtx_unlock(&screen->bo_table_lock); 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci return bo; 521bf215546Sopenharmony_ci} 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_cibool lima_bo_wait(struct lima_bo *bo, uint32_t op, uint64_t timeout_ns) 524bf215546Sopenharmony_ci{ 525bf215546Sopenharmony_ci int64_t abs_timeout; 526bf215546Sopenharmony_ci 527bf215546Sopenharmony_ci if (timeout_ns == 0) 528bf215546Sopenharmony_ci abs_timeout = 0; 529bf215546Sopenharmony_ci else 530bf215546Sopenharmony_ci abs_timeout = os_time_get_absolute_timeout(timeout_ns); 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci if (abs_timeout == OS_TIMEOUT_INFINITE) 533bf215546Sopenharmony_ci abs_timeout = INT64_MAX; 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci struct drm_lima_gem_wait req = { 536bf215546Sopenharmony_ci .handle = bo->handle, 537bf215546Sopenharmony_ci .op = op, 538bf215546Sopenharmony_ci .timeout_ns = abs_timeout, 539bf215546Sopenharmony_ci }; 540bf215546Sopenharmony_ci 541bf215546Sopenharmony_ci return drmIoctl(bo->screen->fd, DRM_IOCTL_LIMA_GEM_WAIT, &req) == 0; 542bf215546Sopenharmony_ci} 543