19f464c52Smaya/* 29f464c52Smaya * Copyright (C) 2017-2019 Lima Project 39f464c52Smaya * 49f464c52Smaya * Permission is hereby granted, free of charge, to any person obtaining a 59f464c52Smaya * copy of this software and associated documentation files (the "Software"), 69f464c52Smaya * to deal in the Software without restriction, including without limitation 79f464c52Smaya * the rights to use, copy, modify, merge, publish, distribute, sublicense, 89f464c52Smaya * and/or sell copies of the Software, and to permit persons to whom the 99f464c52Smaya * Software is furnished to do so, subject to the following conditions: 109f464c52Smaya * 119f464c52Smaya * The above copyright notice and this permission notice shall be included in 129f464c52Smaya * all copies or substantial portions of the Software. 139f464c52Smaya * 149f464c52Smaya * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 159f464c52Smaya * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 169f464c52Smaya * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 179f464c52Smaya * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 189f464c52Smaya * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 199f464c52Smaya * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 209f464c52Smaya * OTHER DEALINGS IN THE SOFTWARE. 219f464c52Smaya * 229f464c52Smaya */ 239f464c52Smaya 249f464c52Smaya#include <stdlib.h> 259f464c52Smaya#include <sys/types.h> 269f464c52Smaya#include <unistd.h> 279f464c52Smaya#include <fcntl.h> 289f464c52Smaya 299f464c52Smaya#include "xf86drm.h" 309f464c52Smaya#include "drm-uapi/lima_drm.h" 319f464c52Smaya 329f464c52Smaya#include "util/u_hash_table.h" 337ec681f3Smrg#include "util/u_math.h" 349f464c52Smaya#include "util/os_time.h" 359f464c52Smaya#include "os/os_mman.h" 369f464c52Smaya 377ec681f3Smrg#include "frontend/drm_driver.h" 389f464c52Smaya 399f464c52Smaya#include "lima_screen.h" 409f464c52Smaya#include "lima_bo.h" 417ec681f3Smrg#include "lima_util.h" 429f464c52Smaya 439f464c52Smayabool lima_bo_table_init(struct lima_screen *screen) 449f464c52Smaya{ 457ec681f3Smrg screen->bo_handles = util_hash_table_create_ptr_keys(); 469f464c52Smaya if (!screen->bo_handles) 479f464c52Smaya return false; 489f464c52Smaya 497ec681f3Smrg screen->bo_flink_names = util_hash_table_create_ptr_keys(); 509f464c52Smaya if (!screen->bo_flink_names) 519f464c52Smaya goto err_out0; 529f464c52Smaya 539f464c52Smaya mtx_init(&screen->bo_table_lock, mtx_plain); 549f464c52Smaya return true; 559f464c52Smaya 569f464c52Smayaerr_out0: 577ec681f3Smrg _mesa_hash_table_destroy(screen->bo_handles, NULL); 589f464c52Smaya return false; 599f464c52Smaya} 609f464c52Smaya 617ec681f3Smrgbool lima_bo_cache_init(struct lima_screen *screen) 627ec681f3Smrg{ 637ec681f3Smrg mtx_init(&screen->bo_cache_lock, mtx_plain); 647ec681f3Smrg list_inithead(&screen->bo_cache_time); 657ec681f3Smrg for (int i = 0; i < NR_BO_CACHE_BUCKETS; i++) 667ec681f3Smrg list_inithead(&screen->bo_cache_buckets[i]); 677ec681f3Smrg 687ec681f3Smrg return true; 697ec681f3Smrg} 707ec681f3Smrg 719f464c52Smayavoid lima_bo_table_fini(struct lima_screen *screen) 729f464c52Smaya{ 739f464c52Smaya mtx_destroy(&screen->bo_table_lock); 747ec681f3Smrg _mesa_hash_table_destroy(screen->bo_handles, NULL); 757ec681f3Smrg _mesa_hash_table_destroy(screen->bo_flink_names, NULL); 767ec681f3Smrg} 777ec681f3Smrg 787ec681f3Smrgstatic void 797ec681f3Smrglima_bo_cache_remove(struct lima_bo *bo) 807ec681f3Smrg{ 817ec681f3Smrg list_del(&bo->size_list); 827ec681f3Smrg list_del(&bo->time_list); 839f464c52Smaya} 849f464c52Smaya 859f464c52Smayastatic void lima_close_kms_handle(struct lima_screen *screen, uint32_t handle) 869f464c52Smaya{ 879f464c52Smaya struct drm_gem_close args = { 889f464c52Smaya .handle = handle, 899f464c52Smaya }; 909f464c52Smaya 919f464c52Smaya drmIoctl(screen->fd, DRM_IOCTL_GEM_CLOSE, &args); 929f464c52Smaya} 939f464c52Smaya 947ec681f3Smrgstatic void 957ec681f3Smrglima_bo_free(struct lima_bo *bo) 967ec681f3Smrg{ 977ec681f3Smrg struct lima_screen *screen = bo->screen; 987ec681f3Smrg 997ec681f3Smrg if (lima_debug & LIMA_DEBUG_BO_CACHE) 1007ec681f3Smrg fprintf(stderr, "%s: %p (size=%d)\n", __func__, 1017ec681f3Smrg bo, bo->size); 1027ec681f3Smrg 1037ec681f3Smrg mtx_lock(&screen->bo_table_lock); 1047ec681f3Smrg _mesa_hash_table_remove_key(screen->bo_handles, 1057ec681f3Smrg (void *)(uintptr_t)bo->handle); 1067ec681f3Smrg if (bo->flink_name) 1077ec681f3Smrg _mesa_hash_table_remove_key(screen->bo_flink_names, 1087ec681f3Smrg (void *)(uintptr_t)bo->flink_name); 1097ec681f3Smrg mtx_unlock(&screen->bo_table_lock); 1107ec681f3Smrg 1117ec681f3Smrg if (bo->map) 1127ec681f3Smrg lima_bo_unmap(bo); 1137ec681f3Smrg 1147ec681f3Smrg lima_close_kms_handle(screen, bo->handle); 1157ec681f3Smrg free(bo); 1167ec681f3Smrg} 1177ec681f3Smrg 1187ec681f3Smrgvoid lima_bo_cache_fini(struct lima_screen *screen) 1197ec681f3Smrg{ 1207ec681f3Smrg mtx_destroy(&screen->bo_cache_lock); 1217ec681f3Smrg 1227ec681f3Smrg list_for_each_entry_safe(struct lima_bo, entry, 1237ec681f3Smrg &screen->bo_cache_time, time_list) { 1247ec681f3Smrg lima_bo_cache_remove(entry); 1257ec681f3Smrg lima_bo_free(entry); 1267ec681f3Smrg } 1277ec681f3Smrg} 1287ec681f3Smrg 1299f464c52Smayastatic bool lima_bo_get_info(struct lima_bo *bo) 1309f464c52Smaya{ 1319f464c52Smaya struct drm_lima_gem_info req = { 1329f464c52Smaya .handle = bo->handle, 1339f464c52Smaya }; 1349f464c52Smaya 1359f464c52Smaya if(drmIoctl(bo->screen->fd, DRM_IOCTL_LIMA_GEM_INFO, &req)) 1369f464c52Smaya return false; 1379f464c52Smaya 1389f464c52Smaya bo->offset = req.offset; 1399f464c52Smaya bo->va = req.va; 1409f464c52Smaya return true; 1419f464c52Smaya} 1429f464c52Smaya 1437ec681f3Smrgstatic unsigned 1447ec681f3Smrglima_bucket_index(unsigned size) 1457ec681f3Smrg{ 1467ec681f3Smrg /* Round down to POT to compute a bucket index */ 1477ec681f3Smrg 1487ec681f3Smrg unsigned bucket_index = util_logbase2(size); 1497ec681f3Smrg 1507ec681f3Smrg /* Clamp the bucket index; all huge allocations will be 1517ec681f3Smrg * sorted into the largest bucket */ 1527ec681f3Smrg bucket_index = CLAMP(bucket_index, MIN_BO_CACHE_BUCKET, 1537ec681f3Smrg MAX_BO_CACHE_BUCKET); 1547ec681f3Smrg 1557ec681f3Smrg /* Reindex from 0 */ 1567ec681f3Smrg return (bucket_index - MIN_BO_CACHE_BUCKET); 1577ec681f3Smrg} 1587ec681f3Smrg 1597ec681f3Smrgstatic struct list_head * 1607ec681f3Smrglima_bo_cache_get_bucket(struct lima_screen *screen, unsigned size) 1617ec681f3Smrg{ 1627ec681f3Smrg return &screen->bo_cache_buckets[lima_bucket_index(size)]; 1637ec681f3Smrg} 1647ec681f3Smrg 1657ec681f3Smrgstatic void 1667ec681f3Smrglima_bo_cache_free_stale_bos(struct lima_screen *screen, time_t time) 1677ec681f3Smrg{ 1687ec681f3Smrg unsigned cnt = 0; 1697ec681f3Smrg list_for_each_entry_safe(struct lima_bo, entry, 1707ec681f3Smrg &screen->bo_cache_time, time_list) { 1717ec681f3Smrg /* Free BOs that are sitting idle for longer than 5 seconds */ 1727ec681f3Smrg if (time - entry->free_time > 6) { 1737ec681f3Smrg lima_bo_cache_remove(entry); 1747ec681f3Smrg lima_bo_free(entry); 1757ec681f3Smrg cnt++; 1767ec681f3Smrg } else 1777ec681f3Smrg break; 1787ec681f3Smrg } 1797ec681f3Smrg if ((lima_debug & LIMA_DEBUG_BO_CACHE) && cnt) 1807ec681f3Smrg fprintf(stderr, "%s: freed %d stale BOs\n", __func__, cnt); 1817ec681f3Smrg} 1827ec681f3Smrg 1837ec681f3Smrgstatic void 1847ec681f3Smrglima_bo_cache_print_stats(struct lima_screen *screen) 1857ec681f3Smrg{ 1867ec681f3Smrg fprintf(stderr, "===============\n"); 1877ec681f3Smrg fprintf(stderr, "BO cache stats:\n"); 1887ec681f3Smrg unsigned total_size = 0; 1897ec681f3Smrg for (int i = 0; i < NR_BO_CACHE_BUCKETS; i++) { 1907ec681f3Smrg struct list_head *bucket = &screen->bo_cache_buckets[i]; 1917ec681f3Smrg unsigned bucket_size = 0; 1927ec681f3Smrg list_for_each_entry(struct lima_bo, entry, bucket, size_list) { 1937ec681f3Smrg bucket_size += entry->size; 1947ec681f3Smrg total_size += entry->size; 1957ec681f3Smrg } 1967ec681f3Smrg fprintf(stderr, "Bucket #%d, BOs: %d, size: %u\n", i, 1977ec681f3Smrg list_length(bucket), 1987ec681f3Smrg bucket_size); 1997ec681f3Smrg } 2007ec681f3Smrg fprintf(stderr, "Total size: %u\n", total_size); 2017ec681f3Smrg} 2027ec681f3Smrg 2037ec681f3Smrgstatic bool 2047ec681f3Smrglima_bo_cache_put(struct lima_bo *bo) 2057ec681f3Smrg{ 2067ec681f3Smrg if (!bo->cacheable) 2077ec681f3Smrg return false; 2087ec681f3Smrg 2097ec681f3Smrg struct lima_screen *screen = bo->screen; 2107ec681f3Smrg 2117ec681f3Smrg mtx_lock(&screen->bo_cache_lock); 2127ec681f3Smrg struct list_head *bucket = lima_bo_cache_get_bucket(screen, bo->size); 2137ec681f3Smrg 2147ec681f3Smrg if (!bucket) { 2157ec681f3Smrg mtx_unlock(&screen->bo_cache_lock); 2167ec681f3Smrg return false; 2177ec681f3Smrg } 2187ec681f3Smrg 2197ec681f3Smrg struct timespec time; 2207ec681f3Smrg clock_gettime(CLOCK_MONOTONIC, &time); 2217ec681f3Smrg bo->free_time = time.tv_sec; 2227ec681f3Smrg list_addtail(&bo->size_list, bucket); 2237ec681f3Smrg list_addtail(&bo->time_list, &screen->bo_cache_time); 2247ec681f3Smrg lima_bo_cache_free_stale_bos(screen, time.tv_sec); 2257ec681f3Smrg if (lima_debug & LIMA_DEBUG_BO_CACHE) { 2267ec681f3Smrg fprintf(stderr, "%s: put BO: %p (size=%d)\n", __func__, bo, bo->size); 2277ec681f3Smrg lima_bo_cache_print_stats(screen); 2287ec681f3Smrg } 2297ec681f3Smrg mtx_unlock(&screen->bo_cache_lock); 2307ec681f3Smrg 2317ec681f3Smrg return true; 2327ec681f3Smrg} 2337ec681f3Smrg 2347ec681f3Smrgstatic struct lima_bo * 2357ec681f3Smrglima_bo_cache_get(struct lima_screen *screen, uint32_t size, uint32_t flags) 2367ec681f3Smrg{ 2377ec681f3Smrg /* we won't cache heap buffer */ 2387ec681f3Smrg if (flags & LIMA_BO_FLAG_HEAP) 2397ec681f3Smrg return NULL; 2407ec681f3Smrg 2417ec681f3Smrg struct lima_bo *bo = NULL; 2427ec681f3Smrg mtx_lock(&screen->bo_cache_lock); 2437ec681f3Smrg struct list_head *bucket = lima_bo_cache_get_bucket(screen, size); 2447ec681f3Smrg 2457ec681f3Smrg if (!bucket) { 2467ec681f3Smrg mtx_unlock(&screen->bo_cache_lock); 2477ec681f3Smrg return false; 2487ec681f3Smrg } 2497ec681f3Smrg 2507ec681f3Smrg list_for_each_entry_safe(struct lima_bo, entry, bucket, size_list) { 2517ec681f3Smrg if (entry->size >= size) { 2527ec681f3Smrg /* Check if BO is idle. If it's not it's better to allocate new one */ 2537ec681f3Smrg if (!lima_bo_wait(entry, LIMA_GEM_WAIT_WRITE, 0)) { 2547ec681f3Smrg if (lima_debug & LIMA_DEBUG_BO_CACHE) { 2557ec681f3Smrg fprintf(stderr, "%s: found BO %p but it's busy\n", __func__, 2567ec681f3Smrg entry); 2577ec681f3Smrg } 2587ec681f3Smrg break; 2597ec681f3Smrg } 2607ec681f3Smrg 2617ec681f3Smrg lima_bo_cache_remove(entry); 2627ec681f3Smrg p_atomic_set(&entry->refcnt, 1); 2637ec681f3Smrg entry->flags = flags; 2647ec681f3Smrg bo = entry; 2657ec681f3Smrg if (lima_debug & LIMA_DEBUG_BO_CACHE) { 2667ec681f3Smrg fprintf(stderr, "%s: got BO: %p (size=%d), requested size %d\n", 2677ec681f3Smrg __func__, bo, bo->size, size); 2687ec681f3Smrg lima_bo_cache_print_stats(screen); 2697ec681f3Smrg } 2707ec681f3Smrg break; 2717ec681f3Smrg } 2727ec681f3Smrg } 2737ec681f3Smrg 2747ec681f3Smrg mtx_unlock(&screen->bo_cache_lock); 2757ec681f3Smrg 2767ec681f3Smrg return bo; 2777ec681f3Smrg} 2787ec681f3Smrg 2799f464c52Smayastruct lima_bo *lima_bo_create(struct lima_screen *screen, 2809f464c52Smaya uint32_t size, uint32_t flags) 2819f464c52Smaya{ 2829f464c52Smaya struct lima_bo *bo; 2837ec681f3Smrg 2847ec681f3Smrg size = align(size, LIMA_PAGE_SIZE); 2857ec681f3Smrg 2867ec681f3Smrg /* Try to get bo from cache first */ 2877ec681f3Smrg bo = lima_bo_cache_get(screen, size, flags); 2887ec681f3Smrg if (bo) 2897ec681f3Smrg return bo; 2907ec681f3Smrg 2919f464c52Smaya struct drm_lima_gem_create req = { 2929f464c52Smaya .size = size, 2939f464c52Smaya .flags = flags, 2949f464c52Smaya }; 2959f464c52Smaya 2969f464c52Smaya if (!(bo = calloc(1, sizeof(*bo)))) 2979f464c52Smaya return NULL; 2989f464c52Smaya 2997ec681f3Smrg list_inithead(&bo->time_list); 3007ec681f3Smrg list_inithead(&bo->size_list); 3017ec681f3Smrg 3029f464c52Smaya if (drmIoctl(screen->fd, DRM_IOCTL_LIMA_GEM_CREATE, &req)) 3039f464c52Smaya goto err_out0; 3049f464c52Smaya 3059f464c52Smaya bo->screen = screen; 3069f464c52Smaya bo->size = req.size; 3077ec681f3Smrg bo->flags = req.flags; 3089f464c52Smaya bo->handle = req.handle; 3097ec681f3Smrg bo->cacheable = !(lima_debug & LIMA_DEBUG_NO_BO_CACHE || 3107ec681f3Smrg flags & LIMA_BO_FLAG_HEAP); 3119f464c52Smaya p_atomic_set(&bo->refcnt, 1); 3129f464c52Smaya 3139f464c52Smaya if (!lima_bo_get_info(bo)) 3149f464c52Smaya goto err_out1; 3159f464c52Smaya 3167ec681f3Smrg if (lima_debug & LIMA_DEBUG_BO_CACHE) 3177ec681f3Smrg fprintf(stderr, "%s: %p (size=%d)\n", __func__, 3187ec681f3Smrg bo, bo->size); 3197ec681f3Smrg 3209f464c52Smaya return bo; 3219f464c52Smaya 3229f464c52Smayaerr_out1: 3239f464c52Smaya lima_close_kms_handle(screen, bo->handle); 3249f464c52Smayaerr_out0: 3259f464c52Smaya free(bo); 3269f464c52Smaya return NULL; 3279f464c52Smaya} 3289f464c52Smaya 3297ec681f3Smrgvoid lima_bo_unreference(struct lima_bo *bo) 3309f464c52Smaya{ 3319f464c52Smaya if (!p_atomic_dec_zero(&bo->refcnt)) 3329f464c52Smaya return; 3339f464c52Smaya 3347ec681f3Smrg /* Try to put it into cache */ 3357ec681f3Smrg if (lima_bo_cache_put(bo)) 3367ec681f3Smrg return; 3379f464c52Smaya 3387ec681f3Smrg lima_bo_free(bo); 3399f464c52Smaya} 3409f464c52Smaya 3419f464c52Smayavoid *lima_bo_map(struct lima_bo *bo) 3429f464c52Smaya{ 3439f464c52Smaya if (!bo->map) { 3449f464c52Smaya bo->map = os_mmap(0, bo->size, PROT_READ | PROT_WRITE, 3459f464c52Smaya MAP_SHARED, bo->screen->fd, bo->offset); 3469f464c52Smaya if (bo->map == MAP_FAILED) 3479f464c52Smaya bo->map = NULL; 3489f464c52Smaya } 3499f464c52Smaya 3509f464c52Smaya return bo->map; 3519f464c52Smaya} 3529f464c52Smaya 3539f464c52Smayavoid lima_bo_unmap(struct lima_bo *bo) 3549f464c52Smaya{ 3559f464c52Smaya if (bo->map) { 3569f464c52Smaya os_munmap(bo->map, bo->size); 3579f464c52Smaya bo->map = NULL; 3589f464c52Smaya } 3599f464c52Smaya} 3609f464c52Smaya 3619f464c52Smayabool lima_bo_export(struct lima_bo *bo, struct winsys_handle *handle) 3629f464c52Smaya{ 3639f464c52Smaya struct lima_screen *screen = bo->screen; 3649f464c52Smaya 3657ec681f3Smrg /* Don't cache exported BOs */ 3667ec681f3Smrg bo->cacheable = false; 3677ec681f3Smrg 3689f464c52Smaya switch (handle->type) { 3699f464c52Smaya case WINSYS_HANDLE_TYPE_SHARED: 3709f464c52Smaya if (!bo->flink_name) { 3719f464c52Smaya struct drm_gem_flink flink = { 3729f464c52Smaya .handle = bo->handle, 3739f464c52Smaya .name = 0, 3749f464c52Smaya }; 3759f464c52Smaya if (drmIoctl(screen->fd, DRM_IOCTL_GEM_FLINK, &flink)) 3769f464c52Smaya return false; 3779f464c52Smaya 3789f464c52Smaya bo->flink_name = flink.name; 3799f464c52Smaya 3809f464c52Smaya mtx_lock(&screen->bo_table_lock); 3817ec681f3Smrg _mesa_hash_table_insert(screen->bo_flink_names, 3829f464c52Smaya (void *)(uintptr_t)bo->flink_name, bo); 3839f464c52Smaya mtx_unlock(&screen->bo_table_lock); 3849f464c52Smaya } 3859f464c52Smaya handle->handle = bo->flink_name; 3869f464c52Smaya return true; 3879f464c52Smaya 3889f464c52Smaya case WINSYS_HANDLE_TYPE_KMS: 3899f464c52Smaya mtx_lock(&screen->bo_table_lock); 3907ec681f3Smrg _mesa_hash_table_insert(screen->bo_handles, 3919f464c52Smaya (void *)(uintptr_t)bo->handle, bo); 3929f464c52Smaya mtx_unlock(&screen->bo_table_lock); 3939f464c52Smaya 3949f464c52Smaya handle->handle = bo->handle; 3959f464c52Smaya return true; 3969f464c52Smaya 3979f464c52Smaya case WINSYS_HANDLE_TYPE_FD: 3989f464c52Smaya if (drmPrimeHandleToFD(screen->fd, bo->handle, DRM_CLOEXEC, 3999f464c52Smaya (int*)&handle->handle)) 4009f464c52Smaya return false; 4019f464c52Smaya 4029f464c52Smaya mtx_lock(&screen->bo_table_lock); 4037ec681f3Smrg _mesa_hash_table_insert(screen->bo_handles, 4049f464c52Smaya (void *)(uintptr_t)bo->handle, bo); 4059f464c52Smaya mtx_unlock(&screen->bo_table_lock); 4069f464c52Smaya return true; 4079f464c52Smaya 4089f464c52Smaya default: 4099f464c52Smaya return false; 4109f464c52Smaya } 4119f464c52Smaya} 4129f464c52Smaya 4139f464c52Smayastruct lima_bo *lima_bo_import(struct lima_screen *screen, 4149f464c52Smaya struct winsys_handle *handle) 4159f464c52Smaya{ 4169f464c52Smaya struct lima_bo *bo = NULL; 4179f464c52Smaya struct drm_gem_open req = {0}; 4189f464c52Smaya uint32_t dma_buf_size = 0; 4199f464c52Smaya unsigned h = handle->handle; 4209f464c52Smaya 4219f464c52Smaya mtx_lock(&screen->bo_table_lock); 4229f464c52Smaya 4239f464c52Smaya /* Convert a DMA buf handle to a KMS handle now. */ 4249f464c52Smaya if (handle->type == WINSYS_HANDLE_TYPE_FD) { 4259f464c52Smaya uint32_t prime_handle; 4269f464c52Smaya off_t size; 4279f464c52Smaya 4289f464c52Smaya /* Get a KMS handle. */ 4299f464c52Smaya if (drmPrimeFDToHandle(screen->fd, h, &prime_handle)) { 4309f464c52Smaya mtx_unlock(&screen->bo_table_lock); 4319f464c52Smaya return NULL; 4329f464c52Smaya } 4339f464c52Smaya 4349f464c52Smaya /* Query the buffer size. */ 4359f464c52Smaya size = lseek(h, 0, SEEK_END); 4369f464c52Smaya if (size == (off_t)-1) { 4379f464c52Smaya mtx_unlock(&screen->bo_table_lock); 4389f464c52Smaya lima_close_kms_handle(screen, prime_handle); 4399f464c52Smaya return NULL; 4409f464c52Smaya } 4419f464c52Smaya lseek(h, 0, SEEK_SET); 4429f464c52Smaya 4439f464c52Smaya dma_buf_size = size; 4449f464c52Smaya h = prime_handle; 4459f464c52Smaya } 4469f464c52Smaya 4479f464c52Smaya switch (handle->type) { 4489f464c52Smaya case WINSYS_HANDLE_TYPE_SHARED: 4499f464c52Smaya bo = util_hash_table_get(screen->bo_flink_names, 4509f464c52Smaya (void *)(uintptr_t)h); 4519f464c52Smaya break; 4529f464c52Smaya case WINSYS_HANDLE_TYPE_KMS: 4539f464c52Smaya case WINSYS_HANDLE_TYPE_FD: 4549f464c52Smaya bo = util_hash_table_get(screen->bo_handles, 4559f464c52Smaya (void *)(uintptr_t)h); 4569f464c52Smaya break; 4579f464c52Smaya default: 4589f464c52Smaya mtx_unlock(&screen->bo_table_lock); 4599f464c52Smaya return NULL; 4609f464c52Smaya } 4619f464c52Smaya 4629f464c52Smaya if (bo) { 4639f464c52Smaya p_atomic_inc(&bo->refcnt); 4647ec681f3Smrg /* Don't cache imported BOs */ 4657ec681f3Smrg bo->cacheable = false; 4669f464c52Smaya mtx_unlock(&screen->bo_table_lock); 4679f464c52Smaya return bo; 4689f464c52Smaya } 4699f464c52Smaya 4709f464c52Smaya if (!(bo = calloc(1, sizeof(*bo)))) { 4719f464c52Smaya mtx_unlock(&screen->bo_table_lock); 4729f464c52Smaya if (handle->type == WINSYS_HANDLE_TYPE_FD) 4739f464c52Smaya lima_close_kms_handle(screen, h); 4749f464c52Smaya return NULL; 4759f464c52Smaya } 4769f464c52Smaya 4777ec681f3Smrg /* Don't cache imported BOs */ 4787ec681f3Smrg bo->cacheable = false; 4797ec681f3Smrg list_inithead(&bo->time_list); 4807ec681f3Smrg list_inithead(&bo->size_list); 4819f464c52Smaya bo->screen = screen; 4829f464c52Smaya p_atomic_set(&bo->refcnt, 1); 4839f464c52Smaya 4849f464c52Smaya switch (handle->type) { 4859f464c52Smaya case WINSYS_HANDLE_TYPE_SHARED: 4869f464c52Smaya req.name = h; 4879f464c52Smaya if (drmIoctl(screen->fd, DRM_IOCTL_GEM_OPEN, &req)) { 4889f464c52Smaya mtx_unlock(&screen->bo_table_lock); 4899f464c52Smaya free(bo); 4909f464c52Smaya return NULL; 4919f464c52Smaya } 4929f464c52Smaya bo->handle = req.handle; 4939f464c52Smaya bo->flink_name = h; 4949f464c52Smaya bo->size = req.size; 4959f464c52Smaya break; 4969f464c52Smaya case WINSYS_HANDLE_TYPE_FD: 4979f464c52Smaya bo->handle = h; 4989f464c52Smaya bo->size = dma_buf_size; 4999f464c52Smaya break; 5009f464c52Smaya default: 5019f464c52Smaya /* not possible */ 5029f464c52Smaya assert(0); 5039f464c52Smaya } 5049f464c52Smaya 5059f464c52Smaya if (lima_bo_get_info(bo)) { 5069f464c52Smaya if (handle->type == WINSYS_HANDLE_TYPE_SHARED) 5077ec681f3Smrg _mesa_hash_table_insert(screen->bo_flink_names, 5089f464c52Smaya (void *)(uintptr_t)bo->flink_name, bo); 5097ec681f3Smrg _mesa_hash_table_insert(screen->bo_handles, 5109f464c52Smaya (void*)(uintptr_t)bo->handle, bo); 5119f464c52Smaya } 5129f464c52Smaya else { 5139f464c52Smaya lima_close_kms_handle(screen, bo->handle); 5149f464c52Smaya free(bo); 5159f464c52Smaya bo = NULL; 5169f464c52Smaya } 5179f464c52Smaya 5189f464c52Smaya mtx_unlock(&screen->bo_table_lock); 5199f464c52Smaya 5209f464c52Smaya return bo; 5219f464c52Smaya} 5229f464c52Smaya 5239f464c52Smayabool lima_bo_wait(struct lima_bo *bo, uint32_t op, uint64_t timeout_ns) 5249f464c52Smaya{ 5257ec681f3Smrg int64_t abs_timeout; 5267ec681f3Smrg 5277ec681f3Smrg if (timeout_ns == 0) 5287ec681f3Smrg abs_timeout = 0; 5297ec681f3Smrg else 5307ec681f3Smrg abs_timeout = os_time_get_absolute_timeout(timeout_ns); 5317ec681f3Smrg 5327ec681f3Smrg if (abs_timeout == OS_TIMEOUT_INFINITE) 5337ec681f3Smrg abs_timeout = INT64_MAX; 5347ec681f3Smrg 5359f464c52Smaya struct drm_lima_gem_wait req = { 5369f464c52Smaya .handle = bo->handle, 5379f464c52Smaya .op = op, 5389f464c52Smaya .timeout_ns = abs_timeout, 5399f464c52Smaya }; 5409f464c52Smaya 5419f464c52Smaya return drmIoctl(bo->screen->fd, DRM_IOCTL_LIMA_GEM_WAIT, &req) == 0; 5429f464c52Smaya} 543