1b8e80941Smrg/* 2b8e80941Smrg * Copyright (C) 2012-2018 Rob Clark <robclark@freedesktop.org> 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20b8e80941Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21b8e80941Smrg * SOFTWARE. 22b8e80941Smrg * 23b8e80941Smrg * Authors: 24b8e80941Smrg * Rob Clark <robclark@freedesktop.org> 25b8e80941Smrg */ 26b8e80941Smrg 27b8e80941Smrg#include <sys/types.h> 28b8e80941Smrg#include <sys/stat.h> 29b8e80941Smrg#include <unistd.h> 30b8e80941Smrg 31b8e80941Smrg#include "freedreno_drmif.h" 32b8e80941Smrg#include "freedreno_priv.h" 33b8e80941Smrg 34b8e80941Smrgstatic pthread_mutex_t table_lock = PTHREAD_MUTEX_INITIALIZER; 35b8e80941Smrg 36b8e80941Smrgstatic uint32_t 37b8e80941Smrgu32_hash(const void *key) 38b8e80941Smrg{ 39b8e80941Smrg return _mesa_hash_data(key, sizeof(uint32_t)); 40b8e80941Smrg} 41b8e80941Smrg 42b8e80941Smrgstatic bool 43b8e80941Smrgu32_equals(const void *key1, const void *key2) 44b8e80941Smrg{ 45b8e80941Smrg return *(const uint32_t *)key1 == *(const uint32_t *)key2; 46b8e80941Smrg} 47b8e80941Smrg 48b8e80941Smrg 49b8e80941Smrgstruct fd_device * kgsl_device_new(int fd); 50b8e80941Smrgstruct fd_device * msm_device_new(int fd); 51b8e80941Smrg 52b8e80941Smrgstruct fd_device * fd_device_new(int fd) 53b8e80941Smrg{ 54b8e80941Smrg struct fd_device *dev; 55b8e80941Smrg drmVersionPtr version; 56b8e80941Smrg 57b8e80941Smrg /* figure out if we are kgsl or msm drm driver: */ 58b8e80941Smrg version = drmGetVersion(fd); 59b8e80941Smrg if (!version) { 60b8e80941Smrg ERROR_MSG("cannot get version: %s", strerror(errno)); 61b8e80941Smrg return NULL; 62b8e80941Smrg } 63b8e80941Smrg 64b8e80941Smrg if (!strcmp(version->name, "msm")) { 65b8e80941Smrg DEBUG_MSG("msm DRM device"); 66b8e80941Smrg if (version->version_major != 1) { 67b8e80941Smrg ERROR_MSG("unsupported version: %u.%u.%u", version->version_major, 68b8e80941Smrg version->version_minor, version->version_patchlevel); 69b8e80941Smrg dev = NULL; 70b8e80941Smrg goto out; 71b8e80941Smrg } 72b8e80941Smrg 73b8e80941Smrg dev = msm_device_new(fd); 74b8e80941Smrg dev->version = version->version_minor; 75b8e80941Smrg#if HAVE_FREEDRENO_KGSL 76b8e80941Smrg } else if (!strcmp(version->name, "kgsl")) { 77b8e80941Smrg DEBUG_MSG("kgsl DRM device"); 78b8e80941Smrg dev = kgsl_device_new(fd); 79b8e80941Smrg#endif 80b8e80941Smrg } else { 81b8e80941Smrg ERROR_MSG("unknown device: %s", version->name); 82b8e80941Smrg dev = NULL; 83b8e80941Smrg } 84b8e80941Smrg 85b8e80941Smrgout: 86b8e80941Smrg drmFreeVersion(version); 87b8e80941Smrg 88b8e80941Smrg if (!dev) 89b8e80941Smrg return NULL; 90b8e80941Smrg 91b8e80941Smrg p_atomic_set(&dev->refcnt, 1); 92b8e80941Smrg dev->fd = fd; 93b8e80941Smrg dev->handle_table = _mesa_hash_table_create(NULL, u32_hash, u32_equals); 94b8e80941Smrg dev->name_table = _mesa_hash_table_create(NULL, u32_hash, u32_equals); 95b8e80941Smrg fd_bo_cache_init(&dev->bo_cache, FALSE); 96b8e80941Smrg fd_bo_cache_init(&dev->ring_cache, TRUE); 97b8e80941Smrg 98b8e80941Smrg return dev; 99b8e80941Smrg} 100b8e80941Smrg 101b8e80941Smrg/* like fd_device_new() but creates it's own private dup() of the fd 102b8e80941Smrg * which is close()d when the device is finalized. 103b8e80941Smrg */ 104b8e80941Smrgstruct fd_device * fd_device_new_dup(int fd) 105b8e80941Smrg{ 106b8e80941Smrg int dup_fd = dup(fd); 107b8e80941Smrg struct fd_device *dev = fd_device_new(dup_fd); 108b8e80941Smrg if (dev) 109b8e80941Smrg dev->closefd = 1; 110b8e80941Smrg else 111b8e80941Smrg close(dup_fd); 112b8e80941Smrg return dev; 113b8e80941Smrg} 114b8e80941Smrg 115b8e80941Smrgstruct fd_device * fd_device_ref(struct fd_device *dev) 116b8e80941Smrg{ 117b8e80941Smrg p_atomic_inc(&dev->refcnt); 118b8e80941Smrg return dev; 119b8e80941Smrg} 120b8e80941Smrg 121b8e80941Smrgstatic void fd_device_del_impl(struct fd_device *dev) 122b8e80941Smrg{ 123b8e80941Smrg int close_fd = dev->closefd ? dev->fd : -1; 124b8e80941Smrg fd_bo_cache_cleanup(&dev->bo_cache, 0); 125b8e80941Smrg _mesa_hash_table_destroy(dev->handle_table, NULL); 126b8e80941Smrg _mesa_hash_table_destroy(dev->name_table, NULL); 127b8e80941Smrg dev->funcs->destroy(dev); 128b8e80941Smrg if (close_fd >= 0) 129b8e80941Smrg close(close_fd); 130b8e80941Smrg} 131b8e80941Smrg 132b8e80941Smrgvoid fd_device_del_locked(struct fd_device *dev) 133b8e80941Smrg{ 134b8e80941Smrg if (!atomic_dec_and_test(&dev->refcnt)) 135b8e80941Smrg return; 136b8e80941Smrg fd_device_del_impl(dev); 137b8e80941Smrg} 138b8e80941Smrg 139b8e80941Smrgvoid fd_device_del(struct fd_device *dev) 140b8e80941Smrg{ 141b8e80941Smrg if (!atomic_dec_and_test(&dev->refcnt)) 142b8e80941Smrg return; 143b8e80941Smrg pthread_mutex_lock(&table_lock); 144b8e80941Smrg fd_device_del_impl(dev); 145b8e80941Smrg pthread_mutex_unlock(&table_lock); 146b8e80941Smrg} 147b8e80941Smrg 148b8e80941Smrgint fd_device_fd(struct fd_device *dev) 149b8e80941Smrg{ 150b8e80941Smrg return dev->fd; 151b8e80941Smrg} 152b8e80941Smrg 153b8e80941Smrgenum fd_version fd_device_version(struct fd_device *dev) 154b8e80941Smrg{ 155b8e80941Smrg return dev->version; 156b8e80941Smrg} 157